from tkinter import*
from PIL import Image,ImageTk
from face_recognition import Face_Recognition
from attendance import Attendance
from Qr_code import Qr_Code

class User:
    def __init__(self,root):
        self.root=root
        self.root.geometry("1000x600+200+50")
        self.root.title("QR Generator")

        #====Background Image
        img3=Image.open(r"college_images\bg.jpg")
        img3=img3.resize((1360,768),Image.ANTIALIAS)
        self.photoimg3=ImageTk.PhotoImage(img3)

        bg_img=Label(self.root,image=self.photoimg3)
        bg_img.place(x=0,y=60,width=1360,height=768)

        title=Label(self.root,text="Student Attendance",font=("times new roman",40),bg='blue',fg='white').place(x=0,y=0,relwidth=1)

        #====STUDENT BUTTOM=========
        img4=Image.open(r"college_images\face_rec.jpg")
        img4=img4.resize((300,300),Image.ANTIALIAS)
        self.photoimg4=ImageTk.PhotoImage(img4)

        b1=Button(bg_img,image=self.photoimg4,command=self.face_data,cursor="hand2")
        b1.place(x=150,y=160,width=300,height=300)

        b1_1=Button(bg_img,text="Face Detector",command=self.face_data,cursor="hand2",font=("times new roman",15,"bold"),bg="white",fg="dark blue")
        b1_1.place(x=150,y=460,width=300,height=40)

        #====DETECT FACE BUTTOM=========
        img5=Image.open(r"college_images\qr1.jpg")
        img5=img5.resize((300,300),Image.ANTIALIAS)
        self.photoimg5=ImageTk.PhotoImage(img5)

        b1=Button(bg_img,image=self.photoimg5,cursor="hand2",command=self.open_qr_code)
        b1.place(x=550,y=160,width=300,height=300)

        b1_1=Button(bg_img,text="QR Code",cursor="hand2",command=self.open_qr_code,font=("times new roman",15,"bold"),bg="white",fg="dark blue")
        b1_1.place(x=550,y=460,width=300,height=40)

    def face_data(self):
        self.new_window=Toplevel(self.root)
        self.app=Face_Recognition(self.new_window)

    def attendance_data(self):
        self.new_window=Toplevel(self.root)
        self.app=Attendance(self.new_window)

    def open_qr_code(self):
        self.new_window=Toplevel(self.root)
        self.app=Qr_Code(self.new_window)

if __name__ == "__main__":
    root=Tk()
    obj=User(root)
    root.mainloop()


class Solution(object):
    def countBinarySubstrings(self, s):
        """
        :type s: str
        :rtype: int
        """
        l = []
        for i, c in enumerate(s):
            if i and s[i - 1] == c:
                l[-1] += 1
            else:
                l.append(1)
        return sum(map(min, l[:-1], l[1:]))


import os
import sys
import argparse
import unittest
import auditor as auditor_py
from google.protobuf.json_format import ParseError

# Absolute path to chrome/src.
SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
SRC_DIR = os.path.abspath(os.path.join(SCRIPT_DIR, "../../.."))
TESTS_DIR = os.path.join(SCRIPT_DIR, "test_data")

# Set via the command line
build_path = ""

class TestTrafficAnnotationAuditor(unittest.TestCase):
  def setUp(self):
    unittest.TestCase.setUp(self)

    path_filters = [os.path.relpath(
      os.path.join(TESTS_DIR, "test_sample_annotations.cc"), SRC_DIR)]
    all_annotations = auditor_py.TrafficAnnotationAuditor.run_extractor(
      path_filters)

    self.auditor_ui = auditor_py.TrafficAnnotationAuditorUI(
      build_path, path_filters, False)

    self.auditor = auditor_py.TrafficAnnotationAuditor()

    self.sample_annotations = {}
    for annotation in all_annotations:
      self.sample_annotations[annotation.unique_id] = annotation

  def test_setup(self):
    """|self.sample_annotations| should include all those inside
    test_data/test_sample_annotations.cc"""
    expected = [
      "ok_annotation", "syntax_error_annotation", "incomplete_error_annotation"]
    self.assertItemsEqual(expected, self.sample_annotations.keys())

  def test_ensure_errors(self):
    """In the |test_sample_annotations.cc| there are some broken annotations.

    This test ensures that TrafficAnnotationAuditorUI catches these errors by
    running from start to finish via |.main()|
    """
    # Suppress |self.auditor_ui.main()| prints to stdout.
    sys.stdout = open(os.devnull, "w")
    self.assertEqual(1, self.auditor_ui.main())   # 1 indicates errors caught.
    sys.stdout = sys.__stdout__

  def test_result_ok(self):
    self.auditor.parse_extractor_output(
      [self.sample_annotations["ok_annotation"]])

    # Assert that correct annotation has been extracted and is OK (no errors).
    self.assertTrue(self.auditor.extracted_annotations)
    self.assertFalse(self.auditor.errors)

  def test_syntax_error(self):
    self.auditor.parse_extractor_output(
      [self.sample_annotations["syntax_error_annotation"]])

    self.assertTrue(self.auditor.errors)
    result = self.auditor.errors[0]
    self.assertEqual(auditor_py.AuditorError.Type.ERROR_SYNTAX, result.type)
    self.assertTrue(
      "sender: \"Cloud Policy\"': Expected \"{\"" in str(result))

  def test_incomplete_error(self):
    self.auditor.parse_extractor_output(
      [self.sample_annotations["incomplete_error_annotation"]])

    self.assertTrue(self.auditor.extracted_annotations)
    self.auditor.run_all_checks()
    self.assertTrue(self.auditor.errors)
    result = self.auditor.errors[0]
    self.assertEqual(
      auditor_py.AuditorError.Type.ERROR_INCOMPLETE_ANNOTATION, result.type)

    expected_missing_fields = [
      "sender", "chrome_policy", "cookies_store",
      "policy_exception_justification"]
    missing_fields = str(result).split(
      "missing fields:", 1)[1].lstrip().split(", ")
    self.assertItemsEqual(expected_missing_fields, missing_fields)

if __name__ == "__main__":
  args_parser = argparse.ArgumentParser(
    description="Unittests for auditor.py")
  args_parser.add_argument(
    "--build-path",
    help="Path to the build directory.",
    default=os.path.join(SRC_DIR, "out/Default"))
  args_parser.add_argument('unittest_args', nargs='*')

  args = args_parser.parse_args()
  build_path = args.build_path
  sys.argv[1:] = args.unittest_args
  unittest.main()


#class Persona:
#    def inicializar(self,nom):
#        self.nombre=nom
#    def mostrar(self):
#        print("Nombre: ",self.nombre)

#persona1=Persona()
#persona1.inicializar("Ivano")
#persona1.mostrar()

#----------------------------------------------------------

class Persona:
    def __init__(self):
        self.nombre=input("Indica tu nombre por favor:  ")
        self.edad=int(input("indica tu edad por favor: "))

    def mostrar(self):
        print("Nombre: ", self.nombre)
        print("Edad: ",self.edad)

class Empleado(Persona):
    def __init__(self):
        super().__init__()
        self.horas=float(input("cuantas horas trabajas?: "))
        self.sueldo=float(input("Cuanto cobras?: "))

    def mostrar(self):
        super().mostrar()
        print("horas: ",self.horas)
        print("Sueldo: ",self.sueldo)

# bloque principal
persona1=Persona()
persona1.mostrar()
empleado1=Empleado()
empleado1.mostrar()


import basf2 as b2

import os
import sys

from caf.framework import CAF
from caf import backends

from reconstruction import add_cosmics_reconstruction

from alignment import setups

b2.set_log_level(b2.LogLevel.INFO)

def main(argv):
    print('Demonstrator of Millepede alignment of CDC layers with CAF')

    inputFiles = []
    for file in argv[0:]:
        inputFiles.append(os.path.abspath(file))

    if not len(inputFiles):
        print('Usage: basf2 caf_cdc_alignment DST_FILE.root [DST_FILE2.root ... ]')
        sys.exit(1)

    print('Input DST files:')
    print(inputFiles)

    reco_path = b2.create_path()
    reco_path.add_module('Progress')
    reco_path.add_module('Gearbox')
    reco_path.add_module('Geometry', excludedComponents=['SVD', 'PXD', 'ARICH', 'BeamPipe', 'EKLM'])
    # Add CDC CR reconstruction.
    add_cosmics_reconstruction(reco_path, components=['CDC'], merge_tracks=True, pruneTracks=False)

    setups.dirty_data = True
    millepede = setups.setup_CDCLayers_GCR_Karim()
    millepede.path = reco_path
    calib_init = millepede.create('cdc_layers_init', inputFiles)
    calib_init.max_iterations = 0
    calib_init.max_files_per_collector_job = 1

    setups.dirty_data = False
    millepede = setups.setup_CDCLayers_GCR_Karim()
    millepede.path = reco_path
    millepede.set_param(1.e-3, 'minPValue')
    calib_std = millepede.create('cdc_layers_std', inputFiles)
    calib_std.max_files_per_collector_job = 1

    calib_std.depends_on(calib_init)

    caf = CAF()

    caf.add_calibration(calib_init)
    caf.add_calibration(calib_std)

    caf.backend = backends.Local(2)

    caf.output_dir = 'caf_output'
    caf.run()

    print("Finished CAF Processing")

if __name__ == "__main__":
    # Pass all arguments after script name as input files
    main(sys.argv[1:])


from django.shortcuts import render
from .serializers import PersonSerializer
# Create your views here.
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Person,Region

from rest_framework.viewsets import ModelViewSet

@api_view(['GET','POST'])
def index(request):
    courses = {
            'course' : 'Python',
            'website': 'Udemy'
        }

    if request.method == 'GET':
        return Response(f'GeT it Bro -{courses}')

    elif request.method == 'POST':
        data = request.data

        return Response(f'Post it Bro -{courses} and You Got it Too {data}')

#crud using apiview

@api_view(['GET','POST','PUT','PATCH','DELETE']) #patch partial update
def person_crud(request):

    if request.method == 'GET':
        person_list = Person.objects.filter(country__isnull = False)
        serializer = PersonSerializer(person_list, many =True)
        return Response(serializer.data)
    elif request.method == 'POST':
        data = request.data
        serializer = PersonSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)

        return Response(serializer.errors)

    elif request.method == 'PATCH':
        data = request.data
        person_id =  Person.objects.get(name = data['name'])
        serializer = PersonSerializer(person_id,data=data, partial= True)

        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)

        return Response(serializer.errors)

    elif request.method == 'PUT': #no partial sob field lagbe
        data = request.data

        serializer = PersonSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors)
    else:
        data = request.data
        person_id = Person.objects.get(name = data['name'])
        person_id.delete()

        return Response('Person Deleted')

class PersonViewSet(ModelViewSet):
    queryset = Person.objects.all()
    serializer_class = PersonSerializer

    def partial_update(self, request, *args, **kwargs):
        return super().partial_update(request, *args, **kwargs)


import cv2
import os
from flask import Flask, render_template

dir_path = os.path.dirname(os.path.realpath(__file__))

# classifiers of various parts:
eye_classifier = cv2.CascadeClassifier(f"{dir_path}"+r"\classifiers\eyes.xml")
face_classifier = cv2.CascadeClassifier(f"{dir_path}"+r"\classifiers\haarcascade_frontalface_default.xml")
fullbody_classifier = cv2.CascadeClassifier(f"{dir_path}"+r"\classifiers\haarcascade_fullbody.xml")

app = Flask(__name__)

@app.route('/')
def main():
    return render_template('index.html')

@app.route('/caps.html')
def cap():
    return render_template('caps.html')

@app.route('/index.html')
def index():
    return render_template('index.html')

# All available eyewears
@app.route('/specs')
def specs():
    apply_goggles(specs.__name__)
    return render_template('index.html')

@app.route('/specs1')
def specs1():
    apply_goggles(specs1.__name__)
    return render_template('index.html')

@app.route('/specs2')
def specs2():
    apply_goggles(specs2.__name__)
    return render_template('index.html')

@app.route('/glass1')
def glass1():
    apply_goggles(glass1.__name__)
    return render_template('index.html')

@app.route('/glass2')
def glass2():
    apply_goggles(glass2.__name__)
    return render_template('index.html')

@app.route('/glass3')
def glass3():
    apply_goggles(glass3.__name__)
    return render_template('index.html')

@app.route('/glass4')
def glass4():
    apply_goggles(glass4.__name__)
    return render_template('index.html')

@app.route('/orangeGlass')
def orangeGlass():
    apply_goggles(orangeGlass.__name__)
    return render_template('index.html')

# All available head wears
@app.route('/cap1')
def cap1():
    apply_cap(cap1.__name__)
    return render_template('caps.html')

@app.route('/cap2')
def cap2():
    apply_cap(cap2.__name__)
    return render_template('caps.html')

@app.route('/crown')
def crown():
    apply_cap(crown.__name__)
    return render_template('caps.html')

@app.route('/cap3')
def cap3():
    apply_cap(cap3.__name__)
    return render_template('caps.html')

@app.route('/cap4')
def cap4():
    apply_cap(cap4.__name__)
    return render_template('caps.html')

@app.route('/cap5')
def cap5():
    apply_cap(cap5.__name__)
    return render_template('caps.html')

@app.route('/cap6')
def cap6():
    apply_cap(cap6.__name__)
    return render_template('caps.html')

@app.route('/cap7')
def cap7():
    apply_cap(cap7.__name__)
    return render_template('caps.html')

@app.route('/headband')
def headband():
    apply_cap(headband.__name__)
    return render_template('caps.html')

def image_resize(img, req_width):
    r = float(req_width) / img.shape[1]
    dim = (req_width, int(img.shape[0] * r))
    img = cv2.resize(img, dim, interpolation=cv2.INTER_AREA)
    return img

def apply_goggles(name):
    cap = cv2.VideoCapture(0)

    while cap.isOpened():
        ret, frame = cap.read()
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)

        print(f"{dir_path}" + fr"\static\{name}.png")
        glasses = cv2.imread(f"{dir_path}" + fr"\static\{name}.png", -1)
        print(glasses)

        if ret:
            faces = face_classifier.detectMultiScale(gray, scaleFactor=1.5, minNeighbors=5)
            for face in faces:
                x, y, w, h = face
                roi_gray = gray[y:y + h, x:x + w]
                roi_color = frame[y:y + h, x:x + w]
                # cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 255, 255), 3)
                # eye classifier:
                eyes = eye_classifier.detectMultiScale(gray, scaleFactor=1.5, minNeighbors=5)
                # plotting eyes:
                for eye in eyes:
                    ex, ey, ew, eh = eye
                    region_of_eyes = roi_gray[ey:ey + eh, ex:ex + ew]
                    # cv2.rectangle(frame, (ex,ey), (ex+ew,ey+eh), (0,255,0), 3)
                    glasses = image_resize(glasses, ew)

                    gh, gw, gc = glasses.shape
                    # print(glasses.shape, eye, frame.shape)
                    for i in range(gh):
                        for j in range(gw):
                            if glasses[i, j][3] != 0:
                                frame[ey + i + 20, ex + j] = glasses[i, j]

            frame = cv2.cvtColor(frame, cv2.COLOR_BGRA2BGR)
        cv2.imshow("dressing room(q-quit, c-click)", frame)

        # If 'q' key from he keyboard is pressed, save the image in the system
        key = cv2.waitKey(10)
        if key == ord("q"):
            break
        if key == ord("c"):
            cv2.imwrite("MyImage.jpg", frame)

    cap.release()
    cv2.destroyAllWindows()

def apply_cap(name):
    cap = cv2.VideoCapture(0)

    while cap.isOpened():
        ret, frame = cap.read()
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        frame = cv2.cvtColor(frame, cv2.COLOR_BGR2BGRA)

        print(f"{dir_path}" + fr"\images\{name}.png")
        cap_img = cv2.imread(f"{dir_path}" + fr"\static\{name}.png", -1)
        print(cap_img)

        if ret:
            faces = face_classifier.detectMultiScale(gray, scaleFactor=1.5, minNeighbors=5)
            for face in faces:
                x, y, w, h = face
                # cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 255, 255), 3)
                cap_img = image_resize(cap_img, w)
                #
                gh, gw, gc = cap_img.shape
                for i in range(gh):
                    for j in range(gw):
                        if cap_img[i, j][3] != 0:
                            frame[y + i - (h // 2) + 5, x + j] = cap_img[i, j]

            frame = cv2.cvtColor(frame, cv2.COLOR_BGRA2BGR)
        cv2.imshow("dressing room(q-quit, c-click)", frame)

        # If 'q' key from he keyboard is pressed, save the image in the system
        key = cv2.waitKey(10)
        if key == ord("q"):
            break
        if key == ord("c"):
            cv2.imwrite("MyImage.jpg", frame)

    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    app.run(debug=True)


def bubble_basic(lst):
    """basic bubble sort"""
    outside_loop_count = 0
    inside_loop_count = 0
    print(lst)
    for i in range(len(lst) - 1):   # for checking upto 2nd to last element
        for j in range(len(lst) - 1):
            print(f"j: {lst[j]}, j+1: {lst[j+1]}")
            if lst[j] > lst[j + 1]:
                print(f"swapping {lst[j]} & {lst[j+1]}")
                lst[j], lst[j + 1] = lst[j + 1], lst[j]
            print(lst)
            inside_loop_count += 1
            print("INSIDE LOOP", inside_loop_count, 'DONE')
        outside_loop_count += 1
        print("OUTSIDE LOOP", outside_loop_count, 'DONE')

lst = [6, 5, 3, 1, 8, 7, 2, 4]
bubble_basic(lst)
print("bubble_basic sort:", lst)


"""
https://codeup.kr/problem.php?id=1905&rid=0
"""

import sys
class recursion_depth:
    def __init__(self, limit):
        self.limit = limit
        self.default_limit = sys.getrecursionlimit()
    def __enter__(self):
        sys.setrecursionlimit(self.limit)
    def __exit__(self, type, value, traceback):
        sys.setrecursionlimit(self.default_limit)

n = input()
n = int(n)

def sum(n):
    if n == 1:
        return n
    return n + sum(n-1)

# print(sum(n))

with recursion_depth(20000):
    print(sum(n))

################################################

import sys
sys.setrecursionlimit(1000000)

n = input()
n = int(n)

def sum(n):
    if n > 1:
        return n + sum(n-1)
    return n

print(sum(n))

###############################################

from functools import reduce

reduce(lambda x,y: x+y, range(n), 0)


'''
这道题是第八章，8-15题
'''

def make_pizza(size,*toppings):
    print(f"\nmaking a {size}-inch pizza with the following topping:")
    for topping in toppings:
        print(f'-{topping}')

import pizza

pizza.make_pizza(16, 'pepperoni')
pizza.make_pizza(12, 'mushroom', 'green peppers')


"""
---------------------------------------------------
This code is part of the AISTATS 2021 submission:
>>> Marienwald, Hannah, Fermanian, Jean-Baptiste & Blanchard, Gilles.
    "High-Dimensional Multi-Task Averaging and Application to Kernel
    Mean Embedding." In International Conference on Artificial
    Intelligence and Statistics. PMLR, 2021. <<<
---------------------------------------------------
KERNEL_preparation.py:
    - precomputes the kernels such that every method can be applied on the
      same data and the results will be comparable.
"""
import sys
sys.path.append('../')
import utiels as u
import AOD_settings as s
import numpy as np
import os
from scipy.io import loadmat

unbiased    = s.unbiased      # unbiased estimation of the MMD^2
replace     = s.replace       # replace negative values of MMD^2 with zero
kw1_A           = s.kw1_A     # kernel width (used for Gaussian kernel)
subsample_size  = s.subsample_size      # number of observations used to estimate the KMEs
num_trials      = s.num_trials          # number of trials (repetitions of experiments)
FN_XA       = s.FN_Datapath+'X_A.mat'   # where the data set is stored
FN_trial    = s.FN_trial                # where the results will be saved

### update as desired ########################################################
kernel = u.Gaussiankernel                       # kernel
# kernel = u.Linearkernel
##############################################################################

# load the data
X_Amat = loadmat(FN_XA)
X_A = X_Amat['X_A']
T,n,D = np.shape(X_A)
num_obs_full = [n]*T
num_obs_sample = [subsample_size]*T
t = np.linspace(0,T-1,T, dtype=int)

for trial in range(num_trials):
    if trial == 0 or np.mod(trial,10) == 0:
        print('... trial = '+str(trial+1)+' / '+str(num_trials))
    np.random.shuffle(t)
    train_idx, test_idx = np.split(t,2)
    subsample_idx = np.random.choice(range(n), subsample_size, replace=False)
    X = X_A[:,subsample_idx,:]

    sum_no_diag_Z, sum_XZ, num_obs_Z = u.compute_test_kernel_sums(X, X_A, T, unbiased, kernel, kw1_A)
    sum_K, sum_no_diag, task_var, num_obs = u.compute_kernel_sums(X, 1., T, kernel, kw1_A)

    # compute average inter task MMD^2 (gives also the estimated kernel matrix of the naive approach)
    G_naive = u.compute_MMD2_matrix_naive(sum_K, sum_no_diag, num_obs, T, unbiased, replace)

    # write G_naive and other needed information
    curr_FN = FN_trial + str(trial) + '/'
    # create result folder
    if not os.path.exists(curr_FN):
        os.makedirs(curr_FN)
    np.savetxt(curr_FN+'G_naive.csv', G_naive, delimiter=',')
    np.savetxt(curr_FN+'sum_K.csv', sum_K, delimiter=',')
    np.savetxt(curr_FN+'sum_no_diag.csv', sum_no_diag, delimiter=',')
    np.savetxt(curr_FN+'task_var.csv', task_var, delimiter=',')
    np.savetxt(curr_FN+'num_obs.csv', num_obs_sample, delimiter=',')
    np.savetxt(curr_FN+'sum_no_diag_Z.csv', sum_no_diag_Z, delimiter=',')
    np.savetxt(curr_FN+'sum_XZ.csv', sum_XZ, delimiter=',')
    np.savetxt(curr_FN+'num_obs_Z.csv', num_obs_full, delimiter=',')
    np.savetxt(curr_FN+'subsample_idx.csv', subsample_idx, delimiter=',')
    np.savetxt(curr_FN+'train_idx.csv', train_idx, delimiter=',', fmt='%i')
    np.savetxt(curr_FN+'test_idx.csv', test_idx, delimiter=',', fmt='%i')


import RPi.GPIO as GPIO
import time
from PyQt5.QtCore import QThread

def safe_sleep(asQthread:bool, seconds:float):
    """[summary]

    Args:
        asQthread (bool): specifiy whether the sleep function is for Qthread or native python
        seconds (float): seconds for sleep function
    """
    if asQthread:
        QThread.msleep(int(seconds*1000))
    else:
        time.sleep(seconds)

class Beeper:
    def __init__(self, buzzerpin = 7, asQthread= False):
        """Control class for buzzer on Rpi

        Args:
            buzzerpin (int, optional): Rpi pin where the buzzer is connected. Defaults to 7.
        """
        self.BuzzerPin = 7

        self.asQthread = asQthread
        GPIO.setmode(GPIO.BOARD)
        GPIO.setup(self.BuzzerPin, GPIO.OUT)
        self.off()

    def setup(self, pin:int):
        """setup the GPIO board, defaults buzzer to LOW/OFF
        """
        GPIO.setmode(GPIO.BOARD)
        # global BuzzerPin
        GPIO.setup(self.BuzzerPin, GPIO.OUT)
        GPIO.output(self.BuzzerPin, GPIO.LOW)

    def beep(self, seconds:float):
        """Beep once for specified time in seconds

        Args:
            seconds (float): seconds the beep sound is produced.
        """
        print('BEEPING')
        GPIO.output(self.BuzzerPin,GPIO.HIGH)
        safe_sleep(self.asQthread, seconds)
        GPIO.output(self.BuzzerPin,GPIO.LOW)

    def beepAction(self, seconds:float, delay:float, repeat:float,):
        """specify a on--off on--off pattern for beep

        Args:
            seconds (float): seconds to beep
            delay (float): time to pause beep
            repeat (float): number of times to repeat the pattern
        """

        for _ in range(repeat):
            self.beep(seconds)
            safe_sleep(self.asQthread, delay)

    def beep_while(self, seconds:float, delay:float, repeat:float):
        # self.inAct = True
        self.action = True
        while self.action:
            self.beepAction(seconds, delay, repeat)
            self.action = False
            break

    def off(self,):
        """switch off the beep
        """
        GPIO.output(self.BuzzerPin,GPIO.LOW)


import pytest

from fixtures.common_models import MessageResponse
from fixtures.constants import ResponseText
from fixtures.userInfo.model import GetUserInfoResponse

class TestGetUserInfo:

    @pytest.mark.positive
    def test_get_user_info(self, app, user_info_):
        """
        Steps.
        1. Register new user
        2. Access to store
        3. Add user info
        4. Try to get user info
        5. Check that status code is 200
        6. Check response
        """
        res = app.user_info.get_user_info(
            user_id=user_info_.user_uuid,
            header=user_info_.header,
            type_response=GetUserInfoResponse,
        )
        assert res.status_code == 200, "Check status code"
        assert res.data.city == user_info_.user_info.address.city, "Check city"
        assert res.data.street == user_info_.user_info.address.street, "Check street"
        assert res.data.email == user_info_.user_info.email, "Check email"

    @pytest.mark.negative
    def test_get_info_of_non_existent_user(self, app, user_info_):
        """
        Steps.
        1. Register new user
        2. Access to store
        3. Add user info
        4. Try to get info of non-existent user
        5. Check that status code is 404
        6. Check response
        """
        res = app.user_info.get_user_info(
            user_id=1000,
            header=user_info_.header,
            type_response=MessageResponse,
        )
        assert res.status_code == 404, "Check status code"
        assert res.data.message == ResponseText.MESSAGE_INFO_NOT_FOUND


"""
Simple graph implementation
"""
from util import Stack, Queue  # These may come in handy
import copy

class Graph:

    """Represent a graph as a dictionary of vertices mapping labels to edges."""

    def __init__(self):
        self.vertices = {}

    def add_vertex(self, vertex_id):
        """
        Add a vertex to the graph.
        """
        if vertex_id in self.vertices:
            print("WARNING: That vertex already exists")
        else:
            self.vertices[vertex_id] = set()

    def add_edge(self, v1, v2):
        """
        Add a directed edge to the graph.
        """
        if v1 in self.vertices and v2 in self.vertices:
            self.vertices[v1].add(v2)
        else:
            raise IndexError("That vertex does not exist!")

    def get_neighbors(self, vertex_id):
        """
        Get all neighbors (edges) of a vertex.
        """
        return self.vertices[vertex_id]

    def bft(self, starting_vertex):
        """
        Print each vertex in breadth-first order
        beginning from starting_vertex.
        """
        # Create an empty queue
        q = Queue()
        # Add the starting vertex_id to the queue
        q.enqueue(starting_vertex)
        # Create an empty set to store visited nodes
        visited = set()
        # While the queue is not empty...
        while q.size() > 0:
            # Dequeue, the first vertex
            v = q.dequeue()
            # Check if it's been visited
            # If it has not been visited...
            if v not in visited:
                # Mark it as visited
                print(v)
                visited.add(v)
                # Then add all neighbors to the back of the queue
                for neighbor in self.get_neighbors(v):
                    q.enqueue(neighbor)

    def dft(self, starting_vertex):
        """
        Print each vertex in depth-first order
        beginning from starting_vertex.
        """
        # Create an empty stack
        s = Stack()
        # Push the starting vertex_id to the stack
        s.push(starting_vertex)
        # Create an empty set to store visited nodes
        visited = set()
        # While the stack is not empty...
        while s.size() > 0:
            # Pop the first vertex
            v = s.pop()
            # Check if it's been visited
            # If it has not been visited...
            if v not in visited:
                # Mark it as visited
                print(v)
                visited.add(v)
                # Then push all neighbors to the top of the stack
                for neighbor in self.get_neighbors(v):
                    s.push(neighbor)

    def dft_recursive(self, starting_vertex, visited=None):
        """
        Print each vertex in depth-first order
        beginning from starting_vertex.

        This should be done using recursion.
        """
        if visited is None:
            visited=set()

        # Check if the node is visited
        if starting_vertex not in visited:
            # Mark it as visited
            visited.add(starting_vertex)
             # Print
            print(starting_vertex)

            for neighbor in self.get_neighbors(starting_vertex):
                self.dft_recursive(neighbor, visited)

    def bfs(self, starting_vertex, destination_vertex):
        """
        Return a list containing the shortest path from
        starting_vertex to destination_vertex in
        breath-first order.
        """
        # Create an empty queue
        q = Queue()
        # Add A PATH TO the starting vertex_id to the queue
        q.enqueue([starting_vertex])
        # Create an empty set to store visited nodes
        visited = set()
        # While the queue is not empty...
        while q.size() > 0:
           # Dequeue, the first PATH
           v = q.dequeue()
           # GRAB THE LAST VERTEX FROM THE PATH
           last_path = v[-1]
           # CHECK IF IT'S THE TARGET
           if last_path == destination_vertex:
               # IF SO, RETURN THE PATH
               return v
           # Check if it's been visited
           if last_path not in visited:
           # If it has not been visited...
               # Mark it as visited
               visited.add(last_path)
               # Then add A PATH TO all neighbors to the back of the queue
               for neighbor in self.get_neighbors(last_path):
                   # (Make a copy of the path before adding)
                v_copy = copy.copy(v)
                v_copy.append(neighbor)
                q.enqueue(v_copy)

    def dfs(self, starting_vertex, destination_vertex):
        """
        Return a list containing a path from
        starting_vertex to destination_vertex in
        depth-first order.
        """
        # create empty stack
        s = Stack()

        # add starting vertex path to stack
        s.push([starting_vertex])

        # Create an empty set to store visited nodes
        visited = set()

        # while stack is not empty
        while s.size() > 0:
            # pop last in path
            v = s.pop()
            # grab first vertex path
            last_path = v[-1]
            # check if it is the target
            if last_path == destination_vertex:
                # if so, return path
                return v
            # check if its been visited
            if last_path not in visited:
                # mark as visited
                visited.add(last_path)
                # Then add A PATH TO all neighbors to the front of the stack
                for neighbor in self.get_neighbors(last_path):
                    # make a copy of the path before adding
                    v_copy = copy.copy(v)
                    v_copy.append(neighbor)
                    s.push(v_copy)

    def dfs_recursive(self, starting_vertex, destination_vertex, visited=None, path=None):
        """
        Return a list containing a path from
        starting_vertex to destination_vertex in
        depth-first order.

        This should be done using recursion.
        """
        # initialize visited
        if visited is None:
            visited = set()

        # initialize path
        if path is None:
            path = []

        # check if starting vertex in visited
        if starting_vertex not in visited:
            # mark as visited
            visited.add(starting_vertex)
            path_copy = path.copy()
            path_copy.append(starting_vertex)

            # if starting vertex is destination return
            if starting_vertex == destination_vertex:
                return path_copy

            for neighbor in self.get_neighbors(starting_vertex):
                new_path = self.dfs_recursive(neighbor, destination_vertex, visited, path_copy)
                if new_path is not None:
                    return new_path

if __name__ == '__main__':
    graph = Graph()  # Instantiate your graph
    # https://github.com/LambdaSchool/Graphs/blob/master/objectives/breadth-first-search/img/bfs-visit-order.png
    graph.add_vertex(1)
    graph.add_vertex(2)
    graph.add_vertex(3)
    graph.add_vertex(4)
    graph.add_vertex(5)
    graph.add_vertex(6)
    graph.add_vertex(7)
    graph.add_edge(5, 3)
    graph.add_edge(6, 3)
    graph.add_edge(7, 1)
    graph.add_edge(4, 7)
    graph.add_edge(1, 2)
    graph.add_edge(7, 6)
    graph.add_edge(2, 4)
    graph.add_edge(3, 5)
    graph.add_edge(2, 3)
    graph.add_edge(4, 6)

    '''
    Should print:
        {1: {2}, 2: {3, 4}, 3: {5}, 4: {6, 7}, 5: {3}, 6: {3}, 7: {1, 6}}
    '''
    print(graph.vertices)

    '''
    Valid BFT paths:
        1, 2, 3, 4, 5, 6, 7
        1, 2, 3, 4, 5, 7, 6
        1, 2, 3, 4, 6, 7, 5
        1, 2, 3, 4, 6, 5, 7
        1, 2, 3, 4, 7, 6, 5
        1, 2, 3, 4, 7, 5, 6
        1, 2, 4, 3, 5, 6, 7
        1, 2, 4, 3, 5, 7, 6
        1, 2, 4, 3, 6, 7, 5
        1, 2, 4, 3, 6, 5, 7
        1, 2, 4, 3, 7, 6, 5
        1, 2, 4, 3, 7, 5, 6
    '''
    print("\n~~ BFT ~~\n")
    graph.bft(1)

    # '''
    # Valid DFT paths:
    #     1, 2, 3, 5, 4, 6, 7
    #     1, 2, 3, 5, 4, 7, 6
    #     1, 2, 4, 7, 6, 3, 5
    #     1, 2, 4, 6, 3, 5, 7
    # '''
    print("\n~~ DFT ~~\n")
    graph.dft(1)
    print("\n~~ DFT Recursive ~~\n")
    graph.dft_recursive(1)

    # '''
    # Valid BFS path:
    #     [1, 2, 4, 6]
    # '''
    print("\n~~ BFS ~~\n")
    print(graph.bfs(1, 6))

    # '''
    # Valid DFS paths:
    #     [1, 2, 4, 6]
    #     [1, 2, 4, 7, 6]
    # '''
    print("\n~~ DFS ~~\n")
    print(graph.dfs(1, 6))
    print("\n~~ Recursive DFS ~~\n")
    print(graph.dfs_recursive(1, 6))


import random
import os
import typing
import logging
import numpy as np
from scipy.optimize import fmin_l_bfgs_b
from scipy.stats import norm
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.gaussian_process.kernels import RBF, ConstantKernel
import matplotlib.pyplot as plt

EXTENDED_EVALUATION = False
# Set `EXTENDED_EVALUATION` to `True` in order to visualize your predictions.
ACQUISITION_FUNCTIONS = [
    "gp_lower_confidence",
    "constraint_weighted_ei",
]  # list of acquisition functions which have been implemented

""" Solution """

class BO_algo(object):
    def __init__(self):
        """Initializes the algorithm with a parameter configuration."""

        # ACQUISITION FUNCTION PARAMETERS
        self.kappa = 1  # hyperparameter for GP lower confidence bound
        self.prev_best_z = np.inf  # previous 'best' sample
        self.acquisition_function_type = ACQUISITION_FUNCTIONS[1]

        print(f"-- Using acquisition function: '{self.acquisition_function_type}")

        self.previous_points = []  # previous evaluation points

        # IMPORTANT: DO NOT REMOVE THOSE ATTRIBUTES AND USE sklearn.gaussian_process.GaussianProcessRegressor instances!
        # Otherwise, the extended evaluation will break.

        # following project outline for kernel parameters
        self.constraint_model = GaussianProcessRegressor(
            kernel=RBF(length_scale=2, length_scale_bounds="fixed")
            * ConstantKernel(constant_value=3.5, constant_value_bounds="fixed")
        )
        self.objective_model = GaussianProcessRegressor(
            kernel=RBF(length_scale=1.5, length_scale_bounds="fixed")
            * ConstantKernel(constant_value=1.5, constant_value_bounds="fixed")
        )

    def next_recommendation(self) -> np.ndarray:
        """
        Recommend the next input to sample.

        Returns
        -------
        recommendation: np.ndarray
            1 x domain.shape[0] array containing the next point to evaluate
        """

        # recommend x which maximizes the acquisition function
        return self.optimize_acquisition_function()

    def optimize_acquisition_function(self) -> np.ndarray:  # DON'T MODIFY THIS FUNCTION
        """
        Optimizes the acquisition function.

        Returns
        -------
        x_opt: np.ndarray
            1 x domain.shape[0] array containing the point that approximately maximizes the acquisition function.
        """

        def objective(x: np.array):
            return -self.acquisition_function(x)

        f_values = []
        x_values = []

        # Restarts the optimization 20 times and pick best solution
        for _ in range(20):
            x0 = domain_x[0, 0] + (domain_x[0, 1] - domain_x[0, 0]) * np.random.rand(1)
            x1 = domain_x[1, 0] + (domain_x[1, 1] - domain_x[1, 0]) * np.random.rand(1)
            result = fmin_l_bfgs_b(
                objective, x0=np.array([x0, x1]), bounds=domain_x, approx_grad=True
            )
            x_values.append(np.clip(result[0], *domain_x[0]))
            f_values.append(result[1])

        ind = np.argmin(f_values)
        return np.atleast_2d(x_values[ind])

    def acquisition_function(self, x: np.ndarray) -> np.ndarray:
        """
        Compute the acquisition function.

        Parameters
        ----------
        x: np.ndarray
            point in the domain of f

        Returns
        ------
        af_value: float
            value of the acquisition function at x
        """

        if self.acquisition_function_type == "constraint_weighted_ei":
            """Return the constraint weighted expected improvement function

            For an overview please refer to Gelbart et al. (2014)
            """
            # evaluate the constraint and objective GPs at X
            obj_mu, obj_sigma = self.objective_model.predict(
                x.reshape(1, -1), return_std=True
            )
            constr_mu, constr_sigma = self.constraint_model.predict(
                x.reshape(1, -1), return_std=True
            )

            # probabilitiy that the constraint is <= 0 is the cdf up to 0
            pr_constr = norm.cdf(0, loc=constr_mu, scale=constr_sigma)

            # define eval_point = (prev_best_z - mu)/sigma, as per Gelbart et al. (2014)
            if self.prev_best_z == np.inf:
                # if there is no previous best, assume zero (equivalently: prev_best_z == obj_mu)
                eval_point = 0
            else:
                eval_point = (self.prev_best_z - obj_mu) / obj_sigma

            # compute expected improvement
            n = norm(loc=0, scale=1)
            ei_obj = obj_sigma * (eval_point * n.cdf(eval_point) + n.pdf(eval_point))

            # multiply EI by the probability of the constraint being met
            return ei_obj * pr_constr

        elif self.acquisition_function_type == "gp_lower_confidence":
            """Return the negative lower confidence bound

            Note:
            - The negative is returned so that the acquisition function can be maximized
            - This method does not take the constraint into account
            """
            (
                mu,
                sigma,
            ) = self.objective_model.predict(x.reshape(1, -1), return_std=True)
            return -(mu - self.kappa * sigma)

        else:
            raise NotImplementedError(
                f"Acquisition function type '{self.acquisition_function_type}' has not been implemented"
            )

    def add_data_point(self, x: np.ndarray, z: float, c: float):
        """
        Add data points to the model.

        Parameters
        ----------
        x: np.ndarray
            point in the domain of f
        z: np.ndarray
            value of the acquisition function at x
        c: np.ndarray
            value of the condition function at x
        """

        assert x.shape == (1, 2)

        curr_point = np.array([[float(x[:, 0]), float(x[:, 1]), float(z), float(c)]])

        if len(self.previous_points) == 0:
            self.previous_points = curr_point
        else:
            # could cast a list to np array every iteration, but just take the
            # hit of using vstack
            self.previous_points = np.vstack((self.previous_points, curr_point))

        # track the current best point which ALSO meets the constraint
        if float(z) < self.prev_best_z and float(c) < 0:
            self.prev_best_z = float(z)

        # fit the Gaussian process prior
        self.constraint_model.fit(
            self.previous_points[:, 0:2], self.previous_points[:, 3]
        )
        self.objective_model.fit(
            self.previous_points[:, 0:2], self.previous_points[:, 2]
        )

    def get_solution(self) -> np.ndarray:
        """
        Return x_opt that is believed to be the minimizer of f.

        Returns
        -------
        solution: np.ndarray
            1 x domain.shape[0] array containing the optimal solution of the problem
        """

        # find the minimum values which also meets the constraint
        idx_with_valid_constr = np.where(self.previous_points[:, 3] < 0)[0]

        if len(idx_with_valid_constr) > 0:
            # something which meets the constraint exists
            min_idx_constr = idx_with_valid_constr[
                np.argmin(self.previous_points[idx_with_valid_constr, 2])
            ]
            x0_min, x1_min, z_min, constr_min = self.previous_points[min_idx_constr]

        else:
            # nothing meets the constraint; just return the minimum
            print(
                "-- WARNING: could not find any sample points which met the constraint"
            )
            min_idx_unconstr = np.argmin(self.previous_points[:, 2])
            x0_min, x1_min, z_min, constr_min = self.previous_points[min_idx_unconstr]

        x_min = np.array([[x0_min, x1_min]])

        print(f"-- Found min z: {z_min}")
        print(f"-- Found x value: {x_min}")
        print(f"-- Has constraint: {constr_min}")

        return x_min

"""
    Toy problem to check  you code works as expected
    IMPORTANT: This example is never used and has nothing in common with the task you
    are evaluated on, it's here only for development and illustration purposes.
"""
domain_x = np.array([[0, 6], [0, 6]])
EVALUATION_GRID_POINTS = 250
CONSTRAINT_OFFSET = (
    -0.8
)  # This is an offset you can change to make the constraint more or less difficult to fulfill
LAMBDA = 0.0  # You shouldn't change this value

def check_in_domain(x) -> bool:
    """Validate input"""
    x = np.atleast_2d(x)
    v_dim_0 = np.all(x[:, 0] >= domain_x[0, 0]) and np.all(x[:, 0] <= domain_x[0, 1])
    v_dim_1 = np.all(x[:, 1] >= domain_x[1, 0]) and np.all(x[:, 0] <= domain_x[1, 1])

    return v_dim_0 and v_dim_1

def f(x) -> np.ndarray:
    """Dummy objective"""
    l1 = lambda x0, x1: np.sin(x0) + x1 - 1

    return l1(x[:, 0], x[:, 1])

def c(x) -> np.ndarray:
    """Dummy constraint"""
    c1 = lambda x, y: np.cos(x) * np.cos(y) - 0.1

    return c1(x[:, 0], x[:, 1]) - CONSTRAINT_OFFSET

def get_valid_opt(f, c, domain) -> typing.Tuple[float, float, np.ndarray, np.ndarray]:
    nx, ny = (EVALUATION_GRID_POINTS, EVALUATION_GRID_POINTS)
    x = np.linspace(domain[0, 0], domain[0, 1], nx)
    y = np.linspace(domain[1, 0], domain[1, 1], ny)
    xv, yv = np.meshgrid(x, y)
    samples = np.array([xv.reshape(-1), yv.reshape(-1)]).T

    true_values = f(samples)
    true_cond = c(samples)
    valid_data_idx = np.where(true_cond < LAMBDA)[0]
    f_opt = np.min(true_values[np.where(true_cond < LAMBDA)])
    x_opt = samples[valid_data_idx][
        np.argmin(true_values[np.where(true_cond < LAMBDA)])
    ]
    f_max = np.max(np.abs(true_values))
    x_max = np.argmax(np.abs(true_values))
    return f_opt, f_max, x_opt, x_max

def perform_extended_evaluation(agent, output_dir="./"):
    fig = plt.figure(figsize=(25, 5), dpi=50)
    nx, ny = (EVALUATION_GRID_POINTS, EVALUATION_GRID_POINTS)
    x = np.linspace(0.0, 6.0, nx)
    y = np.linspace(0.0, 6.0, ny)
    xv, yv = np.meshgrid(x, y)
    x_b, y_b = agent.get_solution().reshape(
        -1,
    )  # reshape to unpack values properly
    samples = np.array([xv.reshape(-1), yv.reshape(-1)]).T
    predictions, stds = agent.objective_model.predict(samples, return_std=True)
    predictions = np.reshape(
        predictions, (EVALUATION_GRID_POINTS, EVALUATION_GRID_POINTS)
    )
    conds = agent.constraint_model.predict(samples)
    conds = np.reshape(conds, (EVALUATION_GRID_POINTS, EVALUATION_GRID_POINTS))

    true_values = f(samples)
    true_cond = c(samples)
    conditions_verif = (true_cond < LAMBDA).astype(float)
    conditions_with_nans = 1 - np.copy(conditions_verif)
    conditions_with_nans[np.where(conditions_with_nans == 0)] = np.nan
    conditions_with_nans = np.reshape(
        conditions_with_nans, (EVALUATION_GRID_POINTS, EVALUATION_GRID_POINTS)
    )
    valid_data_idx = np.where(true_cond < LAMBDA)[0]

    f_opt = np.min(true_values[np.where(true_cond < LAMBDA)])
    x_opt = samples[valid_data_idx][
        np.argmin(true_values[np.where(true_cond < LAMBDA)])
    ]

    sampled_point = np.array(agent.previous_points)

    ax_condition = fig.add_subplot(1, 4, 4)
    im_cond = ax_condition.pcolormesh(
        xv,
        yv,
        conds.reshape((EVALUATION_GRID_POINTS, EVALUATION_GRID_POINTS)),
        shading="auto",
        linewidth=0,
    )
    im_cond.set_edgecolor("face")
    fig.colorbar(im_cond, ax=ax_condition)
    ax_condition.scatter(
        sampled_point[:, 0],
        sampled_point[:, 1],
        cmap="Blues",
        marker="x",
        label="Sampled Point by BO",
        antialiased=True,
        linewidth=0,
    )
    ax_condition.pcolormesh(
        xv,
        yv,
        conditions_with_nans,
        shading="auto",
        cmap="Reds",
        alpha=0.7,
        vmin=0,
        vmax=1.0,
        linewidth=0,
        antialiased=True,
    )
    ax_condition.set_title(
        "Constraint GP Posterior +  True Constraint (Red is Infeasible)"
    )
    ax_condition.legend(fontsize="x-small")

    ax_gp_f = fig.add_subplot(1, 4, 2, projection="3d")
    ax_gp_f.plot_surface(
        X=xv,
        Y=yv,
        Z=predictions,
        rcount=100,
        ccount=100,
        linewidth=0,
        antialiased=False,
    )
    ax_gp_f.set_title("Posterior 3D for Objective")

    ax_gp_c = fig.add_subplot(1, 4, 3, projection="3d")
    ax_gp_c.plot_surface(
        X=xv, Y=yv, Z=conds, rcount=100, ccount=100, linewidth=0, antialiased=False
    )
    ax_gp_c.set_title("Posterior 3D for Constraint")

    ax_predictions = fig.add_subplot(1, 4, 1)
    im_predictions = ax_predictions.pcolormesh(
        xv,
        yv,
        predictions,
        shading="auto",
        label="Posterior",
        linewidth=0,
        antialiased=True,
    )
    im_predictions.set_edgecolor("face")
    fig.colorbar(im_predictions, ax=ax_predictions)
    ax_predictions.pcolormesh(
        xv,
        yv,
        conditions_with_nans,
        shading="auto",
        cmap="Reds",
        alpha=0.7,
        vmin=0,
        vmax=1.0,
        label=" True Infeasible",
        linewidth=0,
        antialiased=True,
    )
    ax_predictions.scatter(x_b, y_b, s=20, marker="x", label="Predicted Value by BO")
    ax_predictions.scatter(
        x_opt[0], x_opt[1], s=20, marker="o", label="True Optimimum Under Constraint"
    )
    ax_predictions.set_title(
        "Objective GP Posterior + True Constraint (Red is Infeasible)"
    )
    ax_predictions.legend(fontsize="x-small")
    figure_path = os.path.join(output_dir, "extended_evaluation.pdf")
    fig.savefig(figure_path)
    plt.show()

def train_on_toy(agent, iteration):
    logging.info("Running model on toy example.")
    seed = 1234
    os.environ["PYTHONHASHSEED"] = str(seed)
    random.seed(seed)
    np.random.seed(seed)
    for j in range(iteration):
        # Get next recommendation
        x = agent.next_recommendation()

        # Check for valid shape
        assert x.shape == (1, domain_x.shape[0]), (
            f"The function next recommendation must return a numpy array of "
            f"shape (1, {domain_x.shape[0]})"
        )

        # Obtain objective and constraint observation
        obj_val = f(x) + np.random.normal(size=(x.shape[0],), scale=0.01)
        cost_val = c(x) + np.random.normal(size=(x.shape[0],), scale=0.005)
        agent.add_data_point(x, obj_val, cost_val)

    # Validate solution
    solution = np.atleast_2d(agent.get_solution())
    assert solution.shape == (1, domain_x.shape[0]), (
        f"The function get solution must return a numpy array of shape ("
        f"1, {domain_x.shape[0]})"
    )

    assert check_in_domain(solution), (
        f"The function get solution must return a point within the "
        f"domain, {solution} returned instead"
    )

    # Compute regret
    f_opt, f_max, x_opt, x_max = get_valid_opt(f, c, domain_x)
    if c(solution) > 0.0:
        regret = 1
    else:
        regret = (f(solution) - f_opt) / f_max

    print(
        f"Optimal value: {f_opt}\nProposed solution {solution}\nSolution value "
        f"{f(solution)}\nRegret{regret}"
    )
    return agent

def main():
    logging.warning(
        "This main method is for illustrative purposes only and will NEVER be called by the checker!\n"
        "The checker always calls run_solution directly.\n"
        "Please implement your solution exclusively in the methods and classes mentioned in the task description."
    )

    seed = 1234
    os.environ["PYTHONHASHSEED"] = str(seed)
    random.seed(seed)
    np.random.seed(seed)
    agent = BO_algo()

    agent = train_on_toy(agent, 20)

    if EXTENDED_EVALUATION:
        perform_extended_evaluation(agent)

if __name__ == "__main__":
    main()


import requests
import time
import hashlib
import hmac
from urllib.parse import urlparse
from position import Position
from exchange_data import get_bitmex

api_id = 'INSERT BITMEX ID HERE'
api_secret = 'INSERT BITMEX SECRET KEY HERE'

# Generates an API signature.
# A signature is HMAC_SHA256(secret, verb + path + expires + data), hex encoded.
# Verb must be uppercased, url is relative, expires must be unix timestamp (in seconds)
# and the data, if present, must be JSON without whitespace between keys.
def generate_signature(secret, verb, url, expires, data):
    """Generate a request signature compatible with BitMEX."""
    # Parse the url so we can remove the base and extract just the path.
    parsedURL = urlparse(url)
    path = parsedURL.path
    if parsedURL.query:
        path = path + '?' + parsedURL.query

    if isinstance(data, (bytes, bytearray)):
        data = data.decode('utf8')

    print("Computing HMAC: %s" % verb + path + str(expires) + data)
    message = verb + path + str(expires) + data

    signature = hmac.new(bytes(secret, 'utf8'), bytes(message, 'utf8'), digestmod=hashlib.sha256).hexdigest()
    return signature

# fetch all position info from bitmex
def get_current_positions(secret, id_api):

    expires = int(round(time.time()) + 5000)
    sig = generate_signature(secret, 'GET', '/api/v1/position', expires, '')

    response = requests.get(
        'https://bitmex.com/api/v1/position',
        headers={'api-expires': str(expires), 'api-key': id_api, 'api-signature': sig},
    )
    positions = response.json()
    return positions

# return list of position objects that represent all OPEN positions
def get_position_list(secret, id_api):
    position_data = get_current_positions(secret, id_api)
    position_list = []

    for positions in position_data:
        if positions['isOpen'] == True:
            pos = Position(positions['symbol'], positions['currentQty'], positions['markValue'], positions['avgEntryPrice'],
            positions['markPrice'], positions['liquidationPrice'], positions['posMargin'], positions['leverage'], positions['unrealisedPnl'], positions['realisedPnl'])

            position_list.append(pos)
    return position_list

# return a concatenated string of all positions, each separated by new lines
def display_positions(secret, id_api):
    position_list = get_position_list(secret, id_api)
    position_string = ""
    total_unrealised_pnl = 0.0
    for pos in position_list:
        total_unrealised_pnl += float(pos.unrealised_pnl)
        position_string += str(pos) + "\n"
    position_string +="\nTotal Unrealised PNL: " + str(format(total_unrealised_pnl/100000000, 'f')) + " XBT"
    return position_string

#BALANCE FUNCTIONS

def balance_info(secret, id_api):
    expires = int(round(time.time()) + 5000)
    sig = generate_signature(secret, 'GET', '/api/v1/user/margin', expires, '')

    response = requests.get(
        'https://bitmex.com/api/v1/user/margin',
        headers={'api-expires': str(expires), 'api-key': id_api, 'api-signature': sig},
    )
    balance_data = response.json()
    return balance_data

def display_balance_info(secret, id_api):
    balance_data = balance_info(secret, id_api)
    balance_string = "Wallet Balance: " + str(format(balance_data['walletBalance'] / 100000000, 'f')) + " XBT" +" | $"+ str(round((balance_data['walletBalance']/100000000)*get_bitmex("xbtusd"), 2)) +"\n" + "Unrealised PNL: " + str(format(balance_data['unrealisedPnl'] / 100000000, 'f')) + " XBT" +" | $"+ str(round((balance_data['unrealisedPnl']/100000000)*get_bitmex("xbtusd"), 2)) +"\n"  + "Margin Balance: " + str(format(balance_data['marginBalance'] / 100000000, 'f')) + " XBT"" | $"+ str(round((balance_data['marginBalance']/100000000)*get_bitmex("xbtusd"), 2)) +"\n" + "Available Balance: " + str(format(balance_data['withdrawableMargin'] / 100000000, 'f')) + " XBT" " | $"+ str(round((balance_data['withdrawableMargin']/100000000)*get_bitmex("xbtusd"), 2)) +"\n"
    return balance_string


# SPDX-License-Identifier: GPL-2.0
#
# Description:
#
# - if tb.config.tc_board_bootmode_tc is set, call
#   tb.config.tc_board_bootmode_tc
# - boot a linux kernel if tb.config.tc_demo_linux_tc_boot_lx
#   is set to 'yes'
# - get booted linux version
# - grep through dmesg and check if strings in
#   tb.config.tc_demo_linux_test_dmesg exist
# - check with devmem2 if the register values defined
#   in the register files tb.config.tc_demo_linux_test_reg_files
#   are identical with the values defined in the files
# - start cmd defined in tb.config.tc_demo_linux_test_basic_cmd
#   and check the returning strings.
# - call testcase names defined in list tb.config.tc_demo_linux_tc_list
#
# used variables
#
# - tb.config.tc_demo_linux_tc_boot_lx
#| if == 'yes' boot a linux kernel
#| default: 'yes'
#
# - tb.config.tc_demo_linux_test_dmesg
#| list of strings, which must be in dmesg
#| default: 'none'
#
# - tb.config.tc_demo_linux_test_reg_files
#| list of register filenames, which get
#| checked with testcase tc_lx_check_reg_file.py
#| default: 'none'
#
# - tb.config.tc_demo_linux_test_basic_cmd
#| list of dictionary with key = 'cmd' and value = 'val'
#| command in 'cmd gets executed and checked if string in 'val'
#| is found. if 'val' == 'undef', no check, only command is
#| executed.
#| default: 'none'
#
# - tb.config.tc_demo_linux_tc_list
#| list of testcasenames, which get called
#| default: 'none'
#
# End:

from tbotlib import tbot

tb.define_variable('tc_demo_linux_tc_boot_lx', 'yes')
tb.define_variable('tc_demo_linux_test_dmesg', 'none')
tb.define_variable('tc_demo_linux_test_reg_files', 'none')
tb.define_variable('tc_demo_linux_test_basic_cmd', 'none')
tb.define_variable('tc_demo_linux_tc_list', 'none')

try:
    tb.config.tc_board_bootmode_tc
except:
    tb.config.tc_board_bootmode_tc = ''

logging.info("args: %s", tb.config.tc_board_bootmode_tc)

if tb.config.tc_demo_linux_tc_boot_lx == 'yes':
    if tb.config.tc_board_bootmode_tc != '':
        tb.config.tc_board_bootmode = 'normal'
        tb.eof_call_tc(tb.config.tc_board_bootmode_tc)

    # call ubot setenv
    tb.set_board_state("u-boot")
    tb.eof_write_cmd(tb.c_con, "version")

save = tb.workfd
tb.workfd = tb.c_con

tb.eof_call_tc("tc_lx_get_version.py")

tb.statusprint("Linux vers: %s" % (tb.config.tc_return))

lx_vers = tb.config.tc_return.split()[0]
tb.statusprint("Linux Version %s" % (lx_vers))

# you can use now the lx_vers for differ between linux versions

tb.set_board_state("linux")

# dmesg checks
if tb.config.tc_demo_linux_test_dmesg != 'none':
    check = tb.config.tc_demo_linux_test_dmesg
    tb.statusprint("linux dmesg checks")
    for tb.config.tc_lx_dmesg_grep_name in check:
        tb.eof_call_tc("tc_lx_dmesg_grep.py")

# register checks
if tb.config.tc_demo_linux_test_reg_files != 'none':
    files = tb.config.tc_demo_linux_test_reg_files
    for tb.config.tc_lx_create_reg_file_name in files:
        tb.eof_call_tc("tc_lx_check_reg_file.py")

# do some basic tests
if tb.config.tc_demo_linux_test_basic_cmd != 'none':
    bcmd = tb.config.tc_demo_linux_test_basic_cmd
    tb.statusprint("start basic checks")
    for bl in bcmd:
        if bl["val"] == 'undef':
            tb.eof_write_cmd(tb.c_con, bl["cmd"])
        else:
            tb.eof_write_cmd_check(tb.c_con, bl["cmd"], bl["val"])

if tb.config.tc_demo_linux_tc_list != 'none':
    tc = tb.config.tc_demo_linux_tc_list
    tb.statusprint("Call board specific testcases")
    for tcname in tc:
        tb.eof_call_tc(tcname)

tb.workfd = save
tb.end_tc(True)


'''
判断 tile是否在视口内
输出: 字典， key为分块的位置与大小， value为(40)数组, 1代表在， 0代表不在
'''
from PSNR import *
import os
import torch
import numpy as np
from def_parser import *
import time

# Get_Mask
# 判断tile与Mask是否有重合
def get_left_top(WIDTH, HEIGHT, tile_width, tile_height):
    '''
    x对应w
    y对应height
    '''
    x_list = []
    y_list = []
    for x in range(0,WIDTH, tile_width):
        for y in range(0, HEIGHT, tile_height):
            x_list.append(x)
            y_list.append(y)
    return x_list, y_list

if __name__ == "__main__":
    parser = basic_parser()
    args = parser.parse_args()
    mp4_folder = '/data/wenxuan/4k_30fps'
    viewpoint_root = '/data/wenxuan/head-tracking-master'
    saved_path = '/data/wenxuan/GCN_data/tile_in_viewpoint_npy'
  #  ALL_VIDEOS = ['AirShow','Surfing', 'Waterskiing',  'F5Fighter', 'StarryPolar', 'BlueWorld', 'BTSRun',  'WaitingForLove',  'LOL']
    ALL_VIDEOS = ['Symphony']
    use_videos = []
    for video in ALL_VIDEOS:
        for tmp_time in time_stamp:
            use_videos.append(tmp_time + '_' +video )
    for video in use_videos:
        t_1 = time.time()
        t, video_name = video.split('_')
        t_begin, t_end = t.split('to')
        t_begin = int(t_begin)
        t_end = int(t_end)
        total_viewpoint = Get_Viewpoint(viewpoint_root, os.path.join(mp4_folder, video_name + '.mp4'), video_name)
        viewpoint = total_viewpoint[:, 30*t_begin:30*t_end, :]
        clientNum = viewpoint.shape[0]
        frameNum = viewpoint.shape[1]
        if not os.path.exists(os.path.join(saved_path, video)):
            os.mkdir(os.path.join(saved_path, video))
        for w in W_size:
            for h in H_size:
                x_list, y_list = get_left_top(args.WIDTH, args.HEIGHT, w, h)
                w_h_dict = {}
                    # 判断tile是否在Mask内
                for i in range(clientNum):
                    for j in range(frameNum):
                        user_frame_dict = {}
                        mask = Get_Mask(args.HEIGHT, args.WIDTH, viewpoint[i, j, 1], viewpoint[i, j, 0]).to(args.device)
                        # 转为float32,防止数值过大
                        pixels = torch.sum(mask)
                        for tile_idx in range(len(x_list)):
                            parameter = '%04d_%04d_%04d_%04d'%(x_list[tile_idx], y_list[tile_idx], w, h)
                            if (mask[y_list[tile_idx]:y_list[tile_idx] + h, x_list[tile_idx]:x_list[tile_idx]+w]).any():
                                # 得到比例
                                view_part = torch.sum(mask[y_list[tile_idx]:y_list[tile_idx] + h, x_list[tile_idx]:x_list[tile_idx]+w])/pixels
                                if args.device == 'cpu':
                                    user_frame_dict[parameter] = view_part.numpy()
                                else:
                                    user_frame_dict[parameter] = view_part.cpu().numpy()
                        w_h_dict['%02d_%02d'%(i,j)] = user_frame_dict
                np.save(os.path.join(saved_path , video,  '%04dx%04d.npy'%(w,h)), w_h_dict)
        print('a video time is {}'.format(time.time() - t_1))
        print("a video {} saved".format(video))


import numpy as np
import os
import pytest
import unittest

from geopyspark.geotrellis import SpatialKey, Extent, Tile, SpatialPartitionStrategy, HashPartitionStrategy
from geopyspark.geotrellis.layer import TiledRasterLayer
from geopyspark.tests.base_test_class import BaseTestClass
from geopyspark.geotrellis.constants import LayerType, Operation, Neighborhood
from geopyspark.geotrellis.neighborhood import Square, Annulus, Wedge, Circle, Nesw

class FocalTest(BaseTestClass):
    cells = np.array([[
        [1.0, 1.0, 1.0, 1.0, 1.0],
        [1.0, 1.0, 1.0, 1.0, 1.0],
        [1.0, 1.0, 1.0, 1.0, 1.0],
        [1.0, 1.0, 1.0, 1.0, 1.0],
        [1.0, 1.0, 1.0, 1.0, 0.0]]])

    tile = Tile.from_numpy_array(cells, -1.0)

    layer = [(SpatialKey(0, 0), tile),
             (SpatialKey(1, 0), tile),
             (SpatialKey(0, 1), tile),
             (SpatialKey(1, 1), tile)]
    rdd = BaseTestClass.pysc.parallelize(layer)

    extent = {'xmin': 0.0, 'ymin': 0.0, 'xmax': 33.0, 'ymax': 33.0}
    layout = {'layoutCols': 2, 'layoutRows': 2, 'tileCols': 5, 'tileRows': 5}
    metadata = {'cellType': 'float32ud-1.0',
                'extent': extent,
                'crs': '+proj=longlat +datum=WGS84 +no_defs ',
                'bounds': {
                    'minKey': {'col': 0, 'row': 0},
                    'maxKey': {'col': 1, 'row': 1}},
                'layoutDefinition': {
                    'extent': extent,
                    'tileLayout': {'tileCols': 5, 'tileRows': 5, 'layoutCols': 2, 'layoutRows': 2}}}

    raster_rdd = TiledRasterLayer.from_numpy_rdd(LayerType.SPATIAL, rdd, metadata)

    @pytest.fixture(autouse=True)
    def tearDown(self):
        yield
        BaseTestClass.pysc._gateway.close()

    def test_focal_sum_square(self):
        result = self.raster_rdd.focal(
            operation=Operation.SUM,
            neighborhood=Neighborhood.SQUARE,
            param_1=1.0,
            partition_strategy=HashPartitionStrategy())

        self.assertTrue(result.to_numpy_rdd().first()[1].cells[0][1][0] >= 6)

    def test_focal_sum_wedge(self):
        neighborhood = Wedge(radius=1.0, start_angle=0.0, end_angle=180.0)
        self.assertEqual(str(neighborhood), repr(neighborhood))

        result = self.raster_rdd.focal(
            operation=Operation.SUM,
            neighborhood=neighborhood,
            partition_strategy=HashPartitionStrategy(2))

        self.assertTrue(result.to_numpy_rdd().first()[1].cells[0][1][0] >= 3)

    def test_focal_sum_circle(self):
        neighborhood = Circle(radius=1.0)
        self.assertEqual(str(neighborhood), repr(neighborhood))

        result = self.raster_rdd.focal(
            operation=Operation.SUM,
            neighborhood=neighborhood,
            partition_strategy=SpatialPartitionStrategy(2))

        self.assertTrue(result.to_numpy_rdd().first()[1].cells[0][1][0] >= 4)

    def test_focal_sum_nesw(self):
        neighborhood = Nesw(extent=1.0)
        self.assertEqual(str(neighborhood), repr(neighborhood))

        result = self.raster_rdd.focal(
            operation=Operation.SUM,
            neighborhood=neighborhood,
            partition_strategy=SpatialPartitionStrategy())

        self.assertTrue(result.to_numpy_rdd().first()[1].cells[0][1][0] >= 4)

    def test_focal_sum_annulus(self):
        neighborhood = Annulus(inner_radius=0.5, outer_radius=1.5)
        self.assertEqual(str(neighborhood), repr(neighborhood))

        result = self.raster_rdd.focal(
            operation=Operation.SUM,
            neighborhood=neighborhood)

        self.assertTrue(result.to_numpy_rdd().first()[1].cells[0][1][0] >= 5.0)

    def test_square(self):
        neighborhood = Square(extent=1.0)
        self.assertEqual(str(neighborhood), repr(neighborhood))

        result = self.raster_rdd.focal(
            operation=Operation.SUM,
            neighborhood=neighborhood)

        self.assertTrue(result.to_numpy_rdd().first()[1].cells[0][1][0] >= 6.0)

    def test_focal_sum_int(self):
        result = self.raster_rdd.focal(
            operation=Operation.SUM,
            neighborhood=Neighborhood.SQUARE,
            param_1=1)

        self.assertTrue(result.to_numpy_rdd().first()[1].cells[0][1][0] >= 6)

    def test_focal_sum_square_with_square(self):
        square = Square(extent=1.0)
        result = self.raster_rdd.focal(
            operation=Operation.SUM,
            neighborhood=square)

        self.assertTrue(result.to_numpy_rdd().first()[1].cells[0][1][0] >= 6)

    def test_focal_min(self):
        result = self.raster_rdd.focal(operation=Operation.MIN, neighborhood=Neighborhood.ANNULUS,
                                       param_1=2.0, param_2=1.0)

        self.assertEqual(result.to_numpy_rdd().first()[1].cells[0][0][0], -1)

    def test_focal_min_annulus(self):
        annulus = Annulus(inner_radius=2.0, outer_radius=1.0)
        result = self.raster_rdd.focal(operation=Operation.MIN, neighborhood=annulus)

        self.assertEqual(result.to_numpy_rdd().first()[1].cells[0][0][0], -1)

    def test_focal_min_int(self):
        result = self.raster_rdd.focal(operation=Operation.MIN, neighborhood=Neighborhood.ANNULUS,
                                       param_1=2, param_2=1)

        self.assertEqual(result.to_numpy_rdd().first()[1].cells[0][0][0], -1)

    def test_tobler(self):
        result = self.raster_rdd.tobler()

if __name__ == "__main__":
    unittest.main()
    BaseTestClass.pysc.stop()


from typing import List, Dict
from transformers import AutoModelForSequenceClassification, AutoTokenizer
from backprop.models import HFModel
import torch

class HFNLIModel(HFModel):
    """
    Class for Hugging Face sequence classification models trained on a NLI dataset

    Attributes:
        model_path: path to HF model
        tokenizer_path: path to HF tokenizer
        name: string identifier for the model. Lowercase letters and numbers.
            No spaces/special characters except dashes.
        description: String description of the model.
        tasks: List of supported task strings
        details: Dictionary of additional details about the model
        model_class: Class used to initialise model
        tokenizer_class: Class used to initialise tokenizer
        device: Device for model. Defaults to "cuda" if available.
    """
    def __init__(self, model_path=None, tokenizer_path=None, name: str = None,
                description: str = None, tasks: List[str] = None, details: Dict = None,
                model_class=AutoModelForSequenceClassification,
                tokenizer_class=AutoTokenizer, device=None):
        tasks = tasks or ["text-classification"]

        HFModel.__init__(self, model_path, name=name, description=description,
                    tasks=tasks, details=details, tokenizer_path=tokenizer_path,
                    model_class=model_class, tokenizer_class=tokenizer_class,
                    device=device)

    @torch.no_grad()
    def __call__(self, task_input, task="text-classification"):
        """
        Uses the model for the text-classification task

        Args:
            task_input: input dictionary according to the ``text-classification`` task specification.
                Needs labels (for zero-shot).
            task: text-classification
        """
        if task == "text-classification":
            is_list = False

            text = task_input.get("text")
            labels = task_input.get("labels")
            top_k = task_input.get("top_k", 10000)

            if labels == None:
                raise ValueError("labels must be provided")

            if isinstance(text, list):
                is_list = True
            else:
                text = [text]
                labels = [labels]

            # Must have a consistent amount of examples
            assert(len(text) == len(labels))

            probs = self.classify(text, labels, top_k)

            if not is_list:
                probs = probs[0]

            return probs
        else:
            raise ValueError(f"Unsupported task: {task}")

    @staticmethod
    def list_models():
        from .models_list import models

        return models

    def calculate_probability(self, text, labels):
        batch_features = []

        hypothesis = [f"This example is {l}." for l in labels]
        features = self.tokenizer([text]*len(hypothesis), hypothesis, return_tensors="pt",
                                    truncation=True, padding=True).to(self._model_device)

        logits = self.model(features["input_ids"], features["attention_mask"])[0]
        entail_contradiction_logits = logits[:, [0, 2]]
        probs = entail_contradiction_logits.softmax(dim=1)
        prob_label_is_true = probs[:, 1]
        return prob_label_is_true.tolist()

    def classify(self, text, labels, top_k):
        """
        Classifies text, given a set of labels.
        """
        probabilities = []
        for text, labels in zip(text, labels):
            probs = {}
            probs_list = self.calculate_probability(text, labels)

            for prob, label in zip(probs_list, labels):
                probs[label] = prob

            probs = sorted(probs.items(), key=lambda x: x[1], reverse=True)
            probs = {k: v for k, v in probs[:top_k]}

            probabilities.append(probs)

        return probabilities


class Vector:
    _cords = []

    def __init__(self, n,j=0):
        self._cords = [j for _ in range(n)]
    def __len__(self):
        return len(self._cords)
    def __eq__(self, other):
        if len(self) != len(other):
            return False
        for i in range(len(self)):
            if self[i] != other[i]:
                return False
        return True
    def __neq__(self, other):
        for i in range(len(self)):
            if self[i] != other[i]:
                return True
        return False
    def __setitem__(self,index, value):
        self._cords[index] = value
    def __getitem__(self, index):
        return self._cords[index]
    def __add__(self,other):
        if len(self) != len(other):
            raise ValueError('vectors must be of equal length')
        rv = Vector(len(self))
        for i in range(len(rv)):
            rv[i] = self[i] + other[i]
        return rv
    def __sub__(self, other):
        if len(self) != len(other):
            raise ValueError('vectors must be of equal length')
        rv = Vector(len(self))
        for i in range(len(rv)):
            rv[i] = self[i] - other[i]
        return rv
    def __repr__(self):
        return 'Vector->{}'.format(self._cords)

my_vector = Vector(3)
my_vector[2] = 5
my_vector_1 = Vector(3,4)
print(my_vector + my_vector_1)
print(my_vector - my_vector_1)
print(my_vector != my_vector_1)
my_vector_3 = Vector(4,3)
try:
    print(my_vector- my_vector_3)
except:
    print('hmmm')
for element in my_vector_3:
    print(element)

Chapter 2 - Object Oriented Programming/tryouts/vector_class.py


import csv
import json
import logging
import sys
from os.path import join
from typing import TextIO, Tuple, Any
import time
import numpy as np
from collections import OrderedDict
from typing import List
from argparse import Namespace
from collections import namedtuple, deque

from utils import utils

LogCfg = namedtuple(
    "LogCfg", ["key_name", "fixed_window", "processing", "abbreviation", "print_format", "print",
               "plot"]
)
"""
    key_name: Key to uniquely identify data (not print log)
    fixed_window: True, If statistics should be calculated on a fixed number of values defined by
        stats_window_size from cfg.main. If so, than we will keep all previous
        (stats_window_size) values and calculate processing on it.
        If not. list will be cleared after each log.
    processing: How to summarize list (mean, average, etc.)  See LOG_TYPES for all possible types.
    abbreviation: Used for print
    print_format: e.g. for print("string_{:.2f}) -> :.2f
    print: If it should be printed
    plot: If it should be plotted
"""

LOG_TYPES = {
    "a": np.mean,  # average list
    "s": np.std,  # standard deviation list
    "m": np.min,  # min from list
    "M": np.max,  # max from list
    "l": lambda x: x[-1],  # last element in list
}

class DataList:
    def __init__(self, fixed_window, values):
        self.fixed_window = fixed_window
        self.values = values

FILE_LOG = "log.txt"
FILE_CSV = "log.csv"
FILE_VOCAB = "vocab.json"
FILE_STATUS = "status.json"

DEFAULT_TRAIN_LOG = [
    LogCfg("update", False, "l", "U", "", True, True),
    LogCfg("num_frames", False, "l", "F", ":06", True, True),
    LogCfg("num_frames_no_off", False, "l", "F0", ":06", False, True),
    LogCfg("fps", False, "a", "FPS", ":04.0f", True, False),
    LogCfg("duration", False, "l", "D", "", True, False),
]

def extra_log_fields(header: list, log_keys: list) ->list:
    unusable_fields = ['return_per_episode', 'reshaped_return_per_episode',
                       'num_frames_per_episode', 'num_frames']
    extra_fields = []
    for field in log_keys:
        if field not in header and field not in unusable_fields:
            extra_fields.append(field)

    return extra_fields

def get_logger(log_dir: str) -> logging.Logger:
    if log_dir is None:
        logging.basicConfig(
            level=logging.INFO,
            format="%(message)s",
        )
    else:
        path = join(log_dir, FILE_LOG)
        utils.create_folders_if_necessary(path)

        logging.basicConfig(
            level=logging.INFO,
            format="%(message)s",
            handlers=[
                logging.FileHandler(filename=path),
                logging.StreamHandler(sys.stdout)
            ]
        )

    return logging.getLogger()

def get_csv_writer(log_dir: str, csv_file_name: str) -> Tuple[TextIO, Any]:
    csv_path = join(log_dir, csv_file_name)
    utils.create_folders_if_necessary(csv_path)
    csv_file = open(csv_path, "a")
    return csv_file, csv.writer(csv_file)

def load_status(log_dir: str) -> dict:
    path = join(log_dir, FILE_STATUS)
    with open(path) as file:
        return json.load(file)

class Header:
    def __init__(self, header_config: List[LogCfg], window_size: int = 1, max_buffer: int = 9999):
        self.window_size = window_size
        self.header = header = OrderedDict()
        self.data = data = dict()
        self._max_buffer = max_buffer

        for ix, cfg in enumerate(header_config):
            key_name = f"{cfg.key_name}_{cfg.processing}"
            key = cfg.key_name
            header[key_name] = Namespace()
            header[key_name].key = key
            header[key_name].process = LOG_TYPES[cfg.processing]
            header[key_name].abbr = cfg.abbreviation
            header[key_name].print_str = cfg.abbreviation + " {" + cfg.print_format + "}"
            header[key_name].print = cfg.print
            header[key_name].fixed_window = cfg.fixed_window
            header[key_name].plot = cfg.plot

            # data window size is configured according to first cfg
            if key not in self.data:
                if cfg.fixed_window:
                    # TODO List growing too big
                    data[key] = DataList(True, [0])
                else:
                    data[key] = DataList(False, [])

    def __getitem__(self, item):
        return self.header[item]

    def reset(self):
        window_size = self.window_size

        for k, v in self.data.items():
            if v.fixed_window:
                v.values = v.values[-window_size:]
            else:
                v.values = []

    def add_data(self, data: dict):
        local_data = self.data
        for k, v in data.items():
            local_data[k].values += v  # Must add only list to logs!
            if len(local_data[k].values) > self._max_buffer:
                local_data[k].values = local_data[k].values[-self._max_buffer:]

    def get_csv_header(self) -> List[str]:
        return self.header.keys()

    def get_values(self) -> List[Any]:
        vs = []
        data = self.data
        win_size = self.window_size
        for kkk, v in self.header.items():
            k = v.key
            if len(data[k].values) > 0:
                if data[k].fixed_window:
                    vs.append(v.process(data[k].values[-win_size:]))
                else:
                    vs.append(v.process(data[k].values))
            else:
                vs.append(None)
        return vs

    def get_win_value(self, key, default=None) -> Any:
        data = self.data
        if len(data[key].values) > 0:
            return np.mean(data[key].values[-self.window_size:])
        else:
            return default

    def get_log(self) -> Tuple[List[str], str, dict]:
        data = self.data
        win_size = self.window_size

        csv_row = []
        print_row = []
        plot_values = dict()

        for kkk, v in self.header.items():
            k = v.key
            if len(data[k].values) > 0:
                if data[k].fixed_window:
                    rv = v.process(data[k].values[-win_size:])
                else:
                    rv = v.process(data[k].values)
            else:
                rv = None

            csv_row.append(rv)
            if v.print:
                print_row.append(v.print_str.format(rv))

            if v.plot:
                plot_values[kkk] = rv

        return csv_row, " | ".join(print_row), plot_values

class DummyCSV:
    def __init__(self):
        pass

    def flush(self):
        pass

class DummyCSVWrite:
    def __init__(self):
        pass

    def writerow(self):
        pass

class LoggerMaster:
    def __init__(self, log_dir: str, plot: bool = False, plot_x: str = None,
                 stats_window_size: int = 1,
                 logger=None, plotter=None, csv_file_name: str = FILE_CSV,
                 plot_project: str = "project-0", experiment: str = "default",
                 cfg: dict = None):
        self.log_dir = log_dir
        self.plot_x = plot_x
        self.window_size = stats_window_size

        self.logger = get_logger(log_dir) if logger is None else logger
        if log_dir is not None:
            self.csv_file, self.csv_writer = get_csv_writer(log_dir, csv_file_name)
        else:
            self.csv_file, self.csv_writer = DummyCSV(), DummyCSVWrite()

        if plot:
            import wandb
            import os

            if os.path.isfile(".wandb_key"):
                with open(".wandb_key") as f:
                    WANDB_API_KEY = f.readline().strip()

                os.environ['WANDB_API_KEY'] = WANDB_API_KEY

            wandb.init(project=plot_project, name=f"{experiment}")
            if cfg is not None:
                wandb.config.update(cfg)
            self.plotter = wandb
        else:
            self.plotter = plotter

        self.total_start_time = time.time()
        self.update_start_time = time.time()

        self.header = None  # type: Header

    def get_plotter(self):
        return self.plotter

    def set_header(self, update, header_config: List[LogCfg]):
        header_config = DEFAULT_TRAIN_LOG + header_config
        self.header = Header(header_config, window_size=self.window_size)

        if update <= 1:
            self.csv_writer.writerow(self.header.get_csv_header())

        self.csv_file.flush()

    def toggle_print(self, toggle_print: List[str]):
        for x in toggle_print:
            if x in self.header.header.keys():
                self.header[x].print = not self.header[x].print

    def toggle_plot(self, toggle_plot: List[str]):
        for x in toggle_plot:
            if x in self.header.header.keys():
                self.header[x].plot = not self.header[x].plot

    def get_logger(self):
        return self.logger

    def register_log(self, update: int, update_num_frames: int, logs: dict):
        update_start_time = time.time()

        num_frames = logs["num_frames"][0]
        logs["update"] = [update]
        logs["fps"] = [update_num_frames / (update_start_time - self.update_start_time)]
        logs["duration"] = [int(time.time() - self.total_start_time)]

        self.update_start_time = update_start_time

        self.header.add_data(logs)

    def log_logs(self):

        csv_row, print_row, plot_values = self.header.get_log()

        self.csv_writer.writerow(csv_row)
        self.csv_file.flush()
        self.logger.info(print_row)

        self.header.reset()

        if self.plotter:
            self.plotter.log(plot_values)


import os
import sys
from pathlib import Path
from typing import Callable, Literal

from typing_extensions import ParamSpec

WINDOWS = sys.platform.startswith("win") or (sys.platform == "cli" and os.name == "nt")

def user_cache_dir(appname: str) -> Path:
    r"""
    Return full path to the user-specific cache dir for this application.
        "appname" is the name of application.
    Typical user cache directories are:
        macOS:      ~/Library/Caches/<AppName>
        Unix:       ~/.cache/<AppName> (XDG default)
        Windows:    C:\Users\<username>\AppData\Local\<AppName>\Cache
    On Windows the only suggestion in the MSDN docs is that local settings go
    in the `CSIDL_LOCAL_APPDATA` directory. This is identical to the
    non-roaming app data dir (the default returned by `user_data_dir`). Apps
    typically put cache data somewhere *under* the given dir here. Some
    examples:
        ...\Mozilla\Firefox\Profiles\<ProfileName>\Cache
        ...\Acme\SuperApp\Cache\1.0
    OPINION: This function appends "Cache" to the `CSIDL_LOCAL_APPDATA` value.
    """
    if WINDOWS:
        return _get_win_folder("CSIDL_LOCAL_APPDATA") / appname / "Cache"
    elif sys.platform == "darwin":
        return Path("~/Library/Caches").expanduser() / appname
    else:
        return Path(os.getenv("XDG_CACHE_HOME", "~/.cache")).expanduser() / appname

def user_data_dir(appname: str, roaming: bool = False) -> Path:
    r"""
    Return full path to the user-specific data dir for this application.
        "appname" is the name of application.
            If None, just the system directory is returned.
        "roaming" (boolean, default False) can be set True to use the Windows
            roaming appdata directory. That means that for users on a Windows
            network setup for roaming profiles, this user data will be
            sync'd on login. See
            <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
            for a discussion of issues.
    Typical user data directories are:
        macOS:                  ~/Library/Application Support/<AppName>
        Unix:                   ~/.local/share/<AppName>    # or in
                                $XDG_DATA_HOME, if defined
        Win XP (not roaming):   C:\Documents and Settings\<username>\ ...
                                ...Application Data\<AppName>
        Win XP (roaming):       C:\Documents and Settings\<username>\Local ...
                                ...Settings\Application Data\<AppName>
        Win 7  (not roaming):   C:\Users\<username>\AppData\Local\<AppName>
        Win 7  (roaming):       C:\Users\<username>\AppData\Roaming\<AppName>
    For Unix, we follow the XDG spec and support $XDG_DATA_HOME.
    That means, by default "~/.local/share/<AppName>".
    """
    if WINDOWS:
        const = "CSIDL_APPDATA" if roaming else "CSIDL_LOCAL_APPDATA"
        return Path(_get_win_folder(const)) / appname
    elif sys.platform == "darwin":
        return Path("~/Library/Application Support/").expanduser() / appname
    else:
        return Path(os.getenv("XDG_DATA_HOME", "~/.local/share")).expanduser() / appname

def user_config_dir(appname: str, roaming: bool = True) -> Path:
    """Return full path to the user-specific config dir for this application.
        "appname" is the name of application.
            If None, just the system directory is returned.
        "roaming" (boolean, default True) can be set False to not use the
            Windows roaming appdata directory. That means that for users on a
            Windows network setup for roaming profiles, this user data will be
            sync'd on login. See
            <http://technet.microsoft.com/en-us/library/cc766489(WS.10).aspx>
            for a discussion of issues.
    Typical user data directories are:
        macOS:                  same as user_data_dir
        Unix:                   ~/.config/<AppName>
        Win *:                  same as user_data_dir
    For Unix, we follow the XDG spec and support $XDG_CONFIG_HOME.
    That means, by default "~/.config/<AppName>".
    """
    if WINDOWS:
        return user_data_dir(appname, roaming=roaming)
    elif sys.platform == "darwin":
        return user_data_dir(appname)
    else:
        return Path(os.getenv("XDG_CONFIG_HOME", "~/.config")).expanduser() / appname

# -- Windows support functions --
def _get_win_folder_from_registry(
    csidl_name: Literal["CSIDL_APPDATA", "CSIDL_COMMON_APPDATA", "CSIDL_LOCAL_APPDATA"]
) -> Path:
    """
    This is a fallback technique at best. I'm not sure if using the
    registry for this guarantees us the correct answer for all CSIDL_*
    names.
    """
    import winreg

    shell_folder_name = {
        "CSIDL_APPDATA": "AppData",
        "CSIDL_COMMON_APPDATA": "Common AppData",
        "CSIDL_LOCAL_APPDATA": "Local AppData",
    }[csidl_name]

    key = winreg.OpenKey(
        winreg.HKEY_CURRENT_USER,
        r"Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders",
    )
    directory, _type = winreg.QueryValueEx(key, shell_folder_name)
    return Path(directory)

def _get_win_folder_with_ctypes(
    csidl_name: Literal["CSIDL_APPDATA", "CSIDL_COMMON_APPDATA", "CSIDL_LOCAL_APPDATA"]
) -> Path:
    csidl_const = {
        "CSIDL_APPDATA": 26,
        "CSIDL_COMMON_APPDATA": 35,
        "CSIDL_LOCAL_APPDATA": 28,
    }[csidl_name]

    buf = ctypes.create_unicode_buffer(1024)
    ctypes.windll.shell32.SHGetFolderPathW(None, csidl_const, None, 0, buf)

    # Downgrade to short path name if have highbit chars. See
    # <http://bugs.activestate.com/show_bug.cgi?id=85099>.
    has_high_char = any(ord(c) > 255 for c in buf)
    if has_high_char:
        buf2 = ctypes.create_unicode_buffer(1024)
        if ctypes.windll.kernel32.GetShortPathNameW(buf.value, buf2, 1024):
            buf = buf2

    return Path(buf.value)

if WINDOWS:
    try:
        import ctypes

        _get_win_folder = _get_win_folder_with_ctypes
    except ImportError:
        _get_win_folder = _get_win_folder_from_registry

P = ParamSpec("P")

APP_NAME = "meme_generator"
BASE_CACHE_DIR = user_cache_dir(APP_NAME).resolve()
BASE_CONFIG_DIR = user_config_dir(APP_NAME).resolve()
BASE_DATA_DIR = user_data_dir(APP_NAME).resolve()

def _ensure_dir(path: Path) -> None:
    if not path.exists():
        path.mkdir(parents=True, exist_ok=True)
    elif not path.is_dir():
        raise RuntimeError(f"{path} is not a directory")

def _auto_create_dir(func: Callable[P, Path]) -> Callable[P, Path]:
    def wrapper(*args: P.args, **kwargs: P.kwargs) -> Path:
        path = func(*args, **kwargs)
        _ensure_dir(path)
        return path

    return wrapper

@_auto_create_dir
def get_cache_dir() -> Path:
    return BASE_CACHE_DIR

def get_cache_file(filename: str) -> Path:
    return get_cache_dir() / filename

@_auto_create_dir
def get_config_dir() -> Path:
    return BASE_CONFIG_DIR

def get_config_file(filename: str) -> Path:
    return get_config_dir() / filename

@_auto_create_dir
def get_data_dir() -> Path:
    return BASE_DATA_DIR

def get_data_file(filename: str) -> Path:
    return get_data_dir() / filename


from src.bias_neuron import BiasNeuron
from src.neural_net import NeuralNet

import networkx as nx
import matplotlib.pyplot as plt

class NetworkXGraphs(object):
    def __init__(self, neural_net):
        self._nn = neural_net

    def draw(self):
        layers = self._nn.get_layers()
        gg = nx.Graph()
        layer_index = 0
        labels = {}
        edge_label = {}
        for l in layers:
            node_index = 0
            for n in l:
                gg.add_node(str(n), pos=(layer_index, node_index))
                labels[str(n)] = round(n.get_value(), 2)
                for c in n.get_connections():
                    gg.add_edge(str(n), str(c.get_neuron()))
                    edge_label[(str(n), str(c.get_neuron()))] = round(c.get_weight(), 2)
                node_index += 1
            layer_index += 1

        pos = nx.get_node_attributes(gg, 'pos')
        plt.subplot()
        nx.draw(gg, pos, with_labels=False, node_size=750)
        nx.draw_networkx_labels(gg, pos, labels)
        nx.draw_networkx_edge_labels(gg, pos, edge_label, label_pos=0.3)
        plt.show()
        plt.pause(0.001)

if __name__ == '__main__':
    nn = NeuralNet([2, 3, 4, 2])
    nn.add_connection(1, 0, 1, 1)
    g = NetworkXGraphs(nn)
    nn.train([[1, 1]], [[1, 0]], 500)
    nn.predict([1, 1])
    g.draw()