import pygame
import main
import sys
from Helpers.button import Button

import settings

def options(screen_width, screen_height):
    buttons_posX = screen_width / 2
    y_start = screen_height / 2
    buttons_posY = [y_start - 300 ,y_start - 200, y_start - 100, y_start , y_start + 150 ,y_start + 300]

    Music_On = True
    Music_label = "Mute Music"
    while True:
        OPTIONS_MOUSE_POS = pygame.mouse.get_pos()

        main.SCREEN.fill("white")

        main.SCREEN.blit(main.BG, (0, 0))

        info = Button(image=None, pos=(buttons_posX, 50),
                            text_input="Left Click to increase - Right Click to decrease",
                            font=main.get_font(20), base_color="White", hovering_color="White")

        Maze_rows = Button(image=None, pos=(buttons_posX, buttons_posY[0]),
                            text_input=f"Number of Maze Rows\t {settings.Number_of_rows}",
                            font=main.get_font(40), base_color="White", hovering_color="#7400b8")

        Maze_Cols = Button(image=None, pos=(buttons_posX, buttons_posY[1]),
                            text_input=f"Number of Maze Columns\t {settings.Number_of_cols}",
                            font=main.get_font(40), base_color="White", hovering_color="#6930c3")

        Kids = Button(image=None, pos=(buttons_posX, buttons_posY[2]),
                        text_input=f"Number of Kids\t {settings.Num_of_kids}",
                        font=main.get_font(40), base_color="White", hovering_color="#5e60ce")

        Time = Button(image=None, pos=(buttons_posX, buttons_posY[3]),
                        text_input=f"Bomb Time :\t {settings.Level_time}",
                        font=main.get_font(40), base_color="White", hovering_color="#5390d9")

        SOUND_BUTTON_MUTE = Button(image=None, pos=(buttons_posX, buttons_posY[4]),
                                   text_input=Music_label, font=main.get_font(60), base_color="White",
                                   hovering_color="#4cc9f0")

        OPTIONS_BACK = Button(image=None, pos=(buttons_posX, buttons_posY[5]),
                              text_input="BACK", font=main.get_font(75), base_color="White",
                              hovering_color="#ff006e")

        for button in [OPTIONS_BACK, SOUND_BUTTON_MUTE, Kids, Maze_rows, Maze_Cols, Time, info]:
            button.changeColor(OPTIONS_MOUSE_POS)
            button.update(main.SCREEN)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if OPTIONS_BACK.checkForInput(OPTIONS_MOUSE_POS):
                    main.main_menu()
                if SOUND_BUTTON_MUTE.checkForInput(OPTIONS_MOUSE_POS):
                    if Music_On:
                        main.mixer.music.stop()
                        Music_label = "UnMute Music"
                        Music_On = False
                    else:
                        main.mixer.music.play()
                        Music_label = "Mute Music"
                        Music_On = True

                if Time.checkForInput(OPTIONS_MOUSE_POS):
                    if event.button == 1:
                        if settings.Level_time == "default":
                            settings.Level_time = 10
                        else:
                            settings.Level_time += 5
                    elif event.button == 3:
                        if settings.Level_time != "default":
                            settings.Level_time -=5
                        if settings.Level_time == 'default' or settings.Level_time <= 0:
                            settings.Level_time = "default"

                if Kids.checkForInput(OPTIONS_MOUSE_POS):
                    if event.button == 1:
                        if settings.Num_of_kids < 100:
                            settings.Num_of_kids +=1
                    elif event.button == 3:
                        if settings.Num_of_kids > 1:
                            settings.Num_of_kids -= 1

                if Maze_Cols.checkForInput(OPTIONS_MOUSE_POS):
                    if event.button == 1:
                        if settings.Number_of_cols < 100:
                            settings.Number_of_cols += 5
                    elif event.button == 3:
                        if settings.Number_of_cols > 5:
                            settings.Number_of_cols -= 5

                if Maze_rows.checkForInput(OPTIONS_MOUSE_POS):
                    if event.button == 1:
                        if settings.Number_of_rows < 100:
                            settings.Number_of_rows += 5
                    elif event.button == 3:
                        if settings.Number_of_rows > 5:
                            settings.Number_of_rows -= 5

        pygame.display.update()


"""
1090. 受标签影响的最大值

我们有一个 n 项的集合。给出两个整数数组 values 和 labels ，第 i 个元素的值和标签分别是 values[i] 和 labels[i]。
还会给出两个整数 numWanted 和 useLimit 。
从 n 个元素中选择一个子集 s :
子集 s 的大小 小于或等于 numWanted 。
s 中 最多 有相同标签的 useLimit 项。
一个子集的 分数 是该子集的值之和。
返回子集 s 的最大 分数 。
"""
import collections
from typing import List

class Solution:
    def largestValsFromLabels(self, values: List[int], labels: List[int], numWanted: int, useLimit: int) -> int:
        label_dict = collections.defaultdict(list)
        for label, value in zip(labels, values):
            label_dict[label].append(value)
        for k, v in label_dict.items():
            label_dict[k] = list(sorted(v, reverse=True))
        candidates = []
        for k, v in label_dict.items():
            candidates.extend(v[:useLimit])
        return sum(list(sorted(candidates, reverse=True))[:numWanted])

1090. 受标签影响的最大值.py


class Node:
	def __init__(self, value):
		self.value = value
		self.next = None

class LinkedList:
	def __init__(self, value):
		self.head = Node(value)

	def insert(self, idx, value):
		new_node = Node(value)
		temp = self.head
		if idx == 0:
			self.head = new_node
			self.head.next = temp
			return True
		else:
			index = 1
			while temp:
				if index == idx:
					next_temp = temp.next
					temp.next = new_node
					new_node.next = next_temp
					return True
				temp = temp.next
			return False

	# O(n) insert at end
	def append(self, value):
		temp = self.head
		while temp.next:
			temp = temp.next
		temp.next = Node(value)

	# O(n) search, returns index if found, -1 otherwise
	def search(self, value):
		temp = self.head
		index = 0
		while temp:
			if temp.value == value:
				return index
			index += 1
			temp = temp.next
		# If not found return -1
		return -1

	# Updates value of node at certain index to value
	# Returns True on success
	def update(self, idx, value):
		temp = self.head
		index = 0

		while temp:
			if index == idx:
				temp.value = value
				return True
			index += 1
			temp = temp.next
		# Return False if index not in list
		return False

	def delete(self, idx):
		temp = self.head

		if idx == 0:
			if temp.next:
				self.head = temp.next
			else:
				self.head = None
			return True

		else:
			index = 1
			while temp.next:
				if index == idx:
					# Update link between nodes to ignore node at idx
					temp.next = temp.next.next
					return True
				index += 1
				temp = temp.next
			# If index not found
			return False

	def __str__(self):
		temp = self.head
		retval = ''
		while temp:
			retval += str(temp.value) + ' -> '
			temp = temp.next
		return retval


'''Meeus: Astronomical Algorithms (2nd ed.), chapter 29'''

import math

from nutation_ecliptic import nutation,ecliptic
from sun import longitude

def PBL(jd):
    '''calculate position angle P, heliographic lat. of center L0, hel. long. of center B0'''
    th=(jd-2398220)*360/25.38
    I=math.radians(7.25)
    K=math.radians(73.6667+1.3958333*(jd-2396758)/36525.)

    psi,eps=nutation(jd)
    eps=math.radians(eps+ecliptic(jd))
    psi=math.radians(psi)

    lon=math.radians(longitude(jd))

    x=math.degrees(math.atan(-math.cos(lon+psi)*math.tan(eps)))
    y=math.degrees(math.atan(-math.cos(lon-K)*math.tan(I)))

    P=x+y
    B=math.degrees(math.asin(math.sin(lon-K)*math.sin(I)))
    nu=math.degrees(math.atan2(-math.sin(lon-K)*math.cos(I),-math.cos(lon-K)))

    L=(nu-th)%360

    return P,B,L

def rotation(jd):
    '''Carrington rotation number'''
    jd0=2398140.10155
    return int(((jd-jd0)/27.2752316)//1)

def rotation_start(n):
    '''time of begining Carrington rotation'''
    jd=2398140.2270+27.2752316*n

    M=math.radians(281.96+26.882476*n)
    return jd+0.1454*math.sin(M)-0.0085*math.sin(2*M)-0.0141*math.cos(2*M)


producto = input("Introduce el nombre del producto\n")
precio = float(input("Introduce su precio\n"))
unidades = int(input("Introduce su numero de unidades\n"))

strprecio = '{:010,.2f}'.format(precio)
strprecio = strprecio.replace(",", "")
strunitario = '{:03,.0f}'.format(unidades)
strunitario = strunitario.replace(",", "")
costetotal = '{:013,.2f}'.format((precio*unidades))
costetotal = costetotal.replace(",", "")

print(f" Nombre del producto: {producto} ...\n Precio Unitario: {strprecio} ...\n Numero de unidades: {strunitario} ...\n Coste Total: {costetotal}")

#str(round(Precio,3)).zfill(3)

#producto = input('Introduce el nombre del producto: ')
#precio = float(input('Introducde el precio unitario: '))
#unidades = int(input('Introduce el número de unidades: '))
#print('{producto}: {unidades:3d} unidades x {precio:6.2f} = {total:8.2f}'.format(producto = producto, unidades = unidades, precio = precio, total = unidades * precio))


import ctypes
from ctypes.wintypes import DWORD, ULONG
from ctypes import windll, c_bool, c_int, POINTER, Structure

from PyQt6 import uic
from PyQt6.QtCore import Qt
from PyQt6.QtGui import QFontDatabase
from UI.uiconstants import UIConst

class AccentPolicy(Structure):
    _fields_ = [
        ('AccentState', DWORD),
        ('AccentFlags', DWORD),
        ('GradientColor', DWORD),
        ('AnimationId', DWORD),
    ]

class WINCOMPATTRDATA(Structure):
    _fields_ = [
        ('Attribute', DWORD),
        ('Data', POINTER(AccentPolicy)),
        ('SizeOfData', ULONG),
    ]

SetWindowCompositionAttribute = windll.user32.SetWindowCompositionAttribute
SetWindowCompositionAttribute.restype = c_bool
SetWindowCompositionAttribute.argtypes = [c_int, POINTER(WINCOMPATTRDATA)]

def blur_background(window):
    window.setWindowFlag(Qt.WindowType.FramelessWindowHint)
    window.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
    accent_policy = AccentPolicy()
    accent_policy.AccentState = 3

    win_comp_attr_data = WINCOMPATTRDATA()
    win_comp_attr_data.Attribute = 19
    win_comp_attr_data.SizeOfData = ctypes.sizeof(accent_policy)
    win_comp_attr_data.Data = ctypes.pointer(accent_policy)

    SetWindowCompositionAttribute(c_int(int(window.winId())), ctypes.pointer(win_comp_attr_data))

def setup_ui_form(window, ui_form):
    with open(f"{UIConst.styles_path}/{window.theme}.css") as style:
        uic.loadUi(f'data/ui/{ui_form}.ui', window)
        QFontDatabase.addApplicationFont(f"{UIConst.fonts_path}/Comfortaa/Comfortaa-Medium.ttf")
        window.setStyleSheet(style.read())
        window.show()


#streamlit run d:/projects/openclassrooms/projets/P7_geran_laurent/homecredit/streamlitApp.py
import numpy as np
import streamlit as st
import matplotlib.pyplot as plt
import requests
import json
import shap
import dataAnalysis

header1 = 'Client Selection'
header2 = 'Description or Comparison'
subheader2_1 = 'Situation at Application'
subheader2_2 = 'Previous Applications'
header3 = 'Score and interpretation'
subheader3_1 = 'Client Score'
subheader3_2 = 'Interpretation'

url_modelAPI = "https://homecredit-model.herokuapp.com/"

url_modelAPI_predict = url_modelAPI+"predict"

st.header(header1)

SK_ID_CURR = int(st.text_input('Please enter a SK_ID_CURR', '100003'))

st.write('The entered SK_ID_CURR is', str(SK_ID_CURR))

st.header(header2)

indiv_currentInit = dataAnalysis.loadData(table='application_train',id = SK_ID_CURR, index = False)
indiv_currentFeat = dataAnalysis.loadData(table='applicationTrain_X',id = SK_ID_CURR)
indiv_currentFeatSelect = dataAnalysis.loadData(table='featSelect',id = SK_ID_CURR)
indiv_currentFeatSelect_X=indiv_currentFeatSelect.drop(columns=['TARGET','SK_ID_CURR'])

payload = json.dumps(indiv_currentFeatSelect_X.to_dict('r')[0])
scoreIndiv = np.round(requests.request("POST", url_modelAPI_predict, data=payload).json()['prediction']*100,1)

ageIndiv = np.floor(-indiv_currentFeat['DAYS_BIRTH'].values[0]/365.5)
loanRateIndiv = np.round(indiv_currentFeat['LOAN_RATE'].values[0]*100,3)
telAgeIndiv = np.floor(-indiv_currentFeat['DAYS_LAST_PHONE_CHANGE'].values[0]/365.5)
previousAppIndiv = indiv_currentFeat['previousAppCounts'].values[0]
longestAppIndiv = indiv_currentFeat['CNT_PAYMENT_max'].values[0]
#longestRemainIndiv = indiv_currentFeat['CNT_INSTALMENT_FUTURE_min_max'].values[0]
maxChangeIndiv = indiv_currentFeat['NUM_INSTALMENT_VERSION_max_max'].values[0]
lastDecisionIndiv = -indiv_currentFeat['DAYS_DECISION_min'].values[0]

repaidStatus = indiv_currentFeatSelect.loc[:,'TARGET']

usage = st.radio(
     'What are you looking for ?',
     ('Description', 'Comparison'))

if usage == 'Comparison':

    criteria = st.multiselect(
    'Which criteria the subsample should have in common with the selected client ?',
    ['Gender', 'Family status'],default=['Gender','Family status'])

    if 'Gender' in criteria:
        gen = indiv_currentInit['CODE_GENDER'].values[0]
    else :
        gen = -1

    if 'Family status' in criteria:
        fam = indiv_currentInit['NAME_FAMILY_STATUS'].values[0]
    else :
        fam = -1

    applicationFeat = dataAnalysis.loadDataCross(table='application_train', gender = gen, family = fam, index = False)

    st.write('You selected the following similitude criteria:', criteria)

    st.subheader(subheader2_1)

    col2_1_1, col2_1_2 = st.columns(2)

    if indiv_currentFeat['x1_F'].values == 0:
        col2_1_1.metric('Gender', 'M')
    else :
        col2_1_1.metric('Gender', 'F')

    ageSample = np.floor(-applicationFeat['daysBirth_avg'].values[0]/365.5)
    col2_1_2.metric('Age', '{age} y'.format(age = ageIndiv), delta = '{ageDelta} y'.format(ageDelta = ageIndiv- ageSample))

    col2_1_3, col2_1_4 = st.columns(2)

    loanRateSample = np.round(applicationFeat['loanRate_avg'].values[0]*100,3)
    col2_1_3.metric('Loan Rate', '{loanRate}%'.format(loanRate = loanRateIndiv), delta = '{loanRateDelta} percentage point'.format(loanRateDelta = np.round(loanRateIndiv- loanRateSample,2)))

    telAgeSample = np.floor(-applicationFeat['daysLastPhoneChange_avg'].values[0]/365.5)
    col2_1_4.metric('Telephone Age',  '{telAge} y'.format(telAge = telAgeIndiv), delta = '{telAgeDelta} y'.format(telAgeDelta = telAgeIndiv- telAgeSample))

    st.subheader(subheader2_2)

    col2_2_1, col2_2_2, col2_2_3  = st.columns(3)

    previousAppSample = np.round(applicationFeat['previousAppCount_avg'].values[0])
    col2_2_1.metric('Number of previous Applications', previousAppIndiv, delta = previousAppIndiv - previousAppSample)

    longestAppSample = np.round(applicationFeat['cntPaymentMax_avg'].values[0])
    col2_2_2.metric('Longest Application', '{longestApp} m'.format(longestApp = longestAppIndiv), delta = '{longestAppDelta} m'.format(longestAppDelta = longestAppIndiv-longestAppSample))

    #longestRemainSample = np.round(applicationFeat['CNT_INSTALMENT_FUTURE_min_max'].mean())
    #col2_2_3.metric('Longest Remaining Installments', longestRemainIndiv, delta = longestRemainIndiv - longestRemainSample)

    col2_2_4, col2_2_5  = st.columns(2)

    maxChangeSample = np.round(applicationFeat['numInstalVersionMaxMax_avg'].values[0])
    col2_2_4.metric('Max Changes in Installment calendar', maxChangeIndiv, delta = maxChangeIndiv - maxChangeSample)

    lastDecisionSample = np.round(-applicationFeat['daysDecisionMin_avg'].values[0])
    col2_2_5.metric('Days since first decision', '{lastDecision} d'.format(lastDecision = lastDecisionIndiv), delta = '{lastDecisionDelta} d'.format(lastDecisionDelta = lastDecisionIndiv-lastDecisionSample))

elif usage == 'Description':

    st.subheader(subheader2_1)

    col2_1_1, col2_1_2 = st.columns(2)

    if indiv_currentFeat['x1_F'].values == 0:
        col2_1_1.metric('Gender', 'M')
    else :
        col2_1_1.metric('Gender', 'F')

    col2_1_2.metric('Age', '{age} y'.format(age = ageIndiv))

    col2_1_3, col2_1_4 = st.columns(2)

    col2_1_3.metric('Loan Rate',  '{loanRate}%'.format(loanRate = loanRateIndiv))

    col2_1_4.metric('Telephone Age',  '{telAge} y'.format(telAge = telAgeIndiv))

    st.subheader(subheader2_2)

    col2_2_1, col2_2_2, col2_2_3  = st.columns(3)

    col2_2_1.metric('Number of previous Applications', previousAppIndiv)

    col2_2_2.metric('Longest Application', '{longestApp} m'.format(longestApp = longestAppIndiv))

    #col2_2_3.metric('Longest Remaining Installments', longestRemainIndiv)

    col2_2_4, col2_2_5  = st.columns(2)

    col2_2_4.metric('Max Changes in Installment calendar', maxChangeIndiv)

    col2_2_5.metric('Days since first decision', '{lastDecision} d'.format(lastDecision = lastDecisionIndiv))

previousApplication = dataAnalysis.loadData('previous_application', SK_ID_CURR, index = False)
installmentsPayments = dataAnalysis.loadData('installments_payments', SK_ID_CURR, index = False)

st.plotly_chart(dataAnalysis.plotHistory(SK_ID_CURR,previousApplication,installmentsPayments), use_container_width=True)

st.header(header3)

st.subheader(subheader3_1)

col3_1, col3_2 = st.columns(2)

col3_1.metric('Score',  '{score}%'.format(score = scoreIndiv))

col3_2.metric ('Repaid status', repaidStatus)

st.subheader(subheader3_2)

url_modelAPI_shap = url_modelAPI+"shap?SK_ID_CURR="+str(SK_ID_CURR)

test = requests.request("GET", url_modelAPI_shap)

response = json.loads(test.json())

shap_values = np.array(response[0])
colums = response[1]
varContribNeg = response[2]

shap.bar_plot(shap_values,feature_names=colums,show=False)
plt.title("Contributions of the 7 more impactful variables")
shapPlot = plt.gcf()

st.pyplot(shapPlot)

st.pyplot(dataAnalysis.kde_target(scoreIndiv,varContribNeg,SK_ID_CURR))


import sys
input = sys.stdin.readline

dr = [-1, 1, 0, 0]
dc = [0, 0, -1, 1]

# 모든 유형의 테트로미노를 탐색하도록 함
def dfs(r, c, idx, total): # idx는 칸의 수, total은 칸에 쓰인 수들의 합
    global ans
    # 가지치기
    if ans >= total + max_val * (3 - idx):
        return
    # 4개의 정사각형을 탐색했으면 리턴
    if idx == 3:
        ans = max(ans, total)
        return
    else:
        for i in range(4):
            nr = r + dr[i]
            nc = c + dc[i]

            if 0 <= nr < N and 0 <= nc < M and visited[nr][nc] == 0:
                # 2번째에서 ㅜ와 ㅁ을 만들 수 있어서
                if idx == 1:
                    visited[nr][nc] = 1
                    dfs(r, c, idx+1, total + arr[nr][nc])
                    visited[nr][nc] = 0
                visited[nr][nc] = 1
                dfs(nr, nc, idx + 1, total + arr[nr][nc])
                visited[nr][nc] = 0

N, M = map(int, input().split()) # N: 세로크기, M: 가로크기
arr = [list(map(int, input().split())) for _ in range(N)]

visited = [[0]*M for _ in range(N)]

ans = 0
max_val = max(map(max, arr))

for i in range(N):
    for j in range(M):
        visited[i][j] = 1
        dfs(i, j, 0, arr[i][j])
        visited[i][j] = 0

print(ans)


import xlrd
from database import db
from database import Books,Students
db.create_all()
# how to delete entire table
# for i in range(1,len(Books.query.all())):
#     book=Books.query.get(i)
#     print(book)
#     db.session.delete(book)
#     db.session.commit()

wb = xlrd.open_workbook('home_book.xlsx')
sh = wb.sheet_by_index(0)
print( sh.cell_value(1,0) )
#3-7735
count=0
for i in range (3,7734):
    # row2 = sh.row(i)
    # if row2[1].find('empty'):
    # print( row2[1])
    if sh.cell_value(i, 1):
        print(f"{count}:{sh.cell_value(i, 1)}:   {sh.cell_value(i, 2)}")
        book = Books(book_topic=sh.cell_value(i, 1).strip(), book_code=sh.cell_value(i, 2).strip())
        db.session.add(book)
        db.session.commit()
    count=count+1


import sys
sys.path.append( '..' )
import stack_api.api_core as api_core
import json
from fastapi import FastAPI, File, UploadFile, Response, Body
from fastapi.middleware.cors import CORSMiddleware
from starlette.responses import StreamingResponse
from pathlib import Path
from pydantic import BaseModel

app = FastAPI()
app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

class Rate(BaseModel):
    label: str

    @classmethod
    def __get_validators__(cls):
        yield cls.validate_to_json

    @classmethod
    def validate_to_json(cls, value):
        if isinstance(value, str):
            return cls(**json.loads(value))
        return value

from src.comm.docker_ver import *
import os
path_home = os.getenv('LCP_DKR')+'/' if docker_ver() else str(Path.home())

# checks if local files are installed
try:
    api = api_core.API(ui=True)
    initialized = api.start_check()
    api.set_schema()
    # print('doing an initial commit')
    # api.commit('',False)
except:
    print('no config file')
    api = api_core.API()
    print('initializing')
    initilized = api.start_check()
    print('trying')
    try:
        api.set_schema()
    except:
        pass
    print('start check')
    if initilized:
        api.start_check()

# frontend entry-points
@app.post("/init_web/")
async def init_web(data: dict):
    # try:
    assert(not '.stack' in data['uri'])

    if path_home in data['uri']:
        data['uri'] = data['uri'].replace(path_home,'')

    api.init(data['uri'])
    api.connect_post_web(data['name'], data, data['schema'], enable_dvc=data['dvc'])
    api.set_schema()
    api.start_check()
    return {'success': True}
    # except:
    #     return {'success': False}

@app.get("/connect/")
async def connect(uri):
    try:
        import time
        t0 = time.time()
        assert(not '.stack' in uri)
        if path_home in uri:
            uri = uri.replace(path_home,'')
        api.init(uri)
        print(f'time to init {time.time() - t0}s')
        t0 = time.time()
        api.connect_post_api()
        print(f'time to connect post api {time.time() - t0}s')
        t0 = time.time()
        api.set_schema()
        print(f'time to set schema {time.time() - t0}s')
        # api.commit()
        t0 = time.time()
        api.reset_version()
        print(f'time to set version {time.time() - t0}s')
        return {'success': True}
    except:
        return {'success': False}

@app.post("/init_gskey/")
def init_gskey(file: UploadFile = File(description="A file read as UploadFile")):
    try:
        api.set_gs_key(file.file)
        return {'success': True}
    except:
        return {'success': False}

@app.post("/set_branch")
def set_branch_api(data: dict):
    # try:
    parent = api.Initializer.storage.dataset
    api.set_hierarchy(child = data['branch_name'])
    api.branch(data['branch_name'], data['branch_type'], data['branch_title'])
    api.set_hierarchy(parent = parent)
    api.set_hierarchies()
    return {'success': True}
    # except:
    #     return {'success': False}

@app.get("/get_hierarchies")
def get_hierarchies_api():
    # try:
    return api.get_hierarchies()

@app.get("/get_current_hierarchy")
def get_current_hierarchy_api():
    try:
        hierarchy = api.get_hierarchy()
        children = []
        for uri in hierarchy['children']:
            children.append({'uri': uri, 'name': api.get_dataset_name(uri)})
        parent = {'uri': hierarchy['parent'], 'name': api.get_dataset_name(hierarchy['parent'])}
        return {'parent': parent, 'children': children}
    except:
        return {'parent': {'uri': '', 'name': ''}, 'children': []}

@app.get("/get_hierarchy")
def get_hierarchy_api(uri):
    try:
        assert(not '.stack' in uri)
        if path_home in uri:
            uri = uri.replace(path_home,'')
        api.init(uri)
        api.connect_post_api()
        return api.get_hierarchy()
    except:
        return {'parent': '', 'children': []}

@app.get("/get_versions")
def get_versions_api():
    try:
        return api.get_versions()
    except:
        return {}

@app.get("/add_version")
def add_version_api(label = ''):
    # try:
    return {'success': api.add_version(label)}
    # except:
    #     return {'success': False}

@app.get("/reset_version")
def reset_version_api():
    try:
        return {'success': api.reset_version()}
    except:
        return {'success': False}

@app.get("/select_version")
def select_version_api(version):
    # try:
    return {'success': api.select_version(str(version))}
    # except:
    #     return {'success': False}

@app.get("/get_branches")
def get_branches_api():
    try:
        hierarchy = api.get_hierarchy()
        res = []
        for uri in hierarchy['children']:
            res.append({'uri': uri, 'name': api.get_dataset_name(uri)})
        return res
    except:
        return []

@app.get("/set_hierarchy")
def set_hierarchy_api(uri_parent, uri_child):
    try:
        assert((not '.stack' in uri_parent) and (not '.stack' in uri_child))

        uri_parent = uri_parent.replace(path_home,'')
        uri_child = uri_child.replace(path_home,'')

        api.init(uri_parent)
        api.connect_post_api()
        api.set_schema()
        api.set_hierarchy(child = uri_child)

        api.init(uri_child)
        api.connect_post_api()
        api.set_schema()
        api.set_hierarchy(parent = uri_parent)

        return {'success': True}
    except:
        return {'success': False}

@app.post("/set_current_hierarchy")
def set_current_hierarchy_api(hierarchy: dict):
    try:
        assert('parent' in hierarchy.keys())
        assert('children' in hierarchy.keys())

        assert(type(hierarchy['parent']) is str)
        assert(type(hierarchy['children']) is list)

        return {'success': api.set_current_hierarchy(hierarchy)}
    except:
        return {'success': {'parent': '', 'children': []}}

@app.get("/add_child_to_current")
def add_child_to_current_api(child):
    try:
        child = child.replace(path_home,'')
        api.add_child_to_current(child)
        parent = api.Initializer.storage.dataset
        parent = parent.replace(path_home,'')
        try:
            api.init(child)
            api.connect_post_api()
            api.set_schema()
            api.add_parent_to_current(parent)
        except:
            pass
        api.init(parent)
        api.connect_post_api()
        api.set_schema()
        api.set_hierarchies()
        return {'success': True}
    except:
        return {'success': False}

@app.get("/add_parent_to_current")
def add_parent_to_current_api(parent):
    try:
        parent = parent.replace(path_home,'')
        api.add_parent_to_current(parent)
        child = api.Initializer.storage.dataset
        child = child.replace(path_home,'')
        try:
            api.init(parent)
            api.connect_post_api()
            api.set_schema()
            api.add_child_to_current(child)
        except:
            pass
        api.init(child)
        api.connect_post_api()
        api.set_schema()
        api.set_hierarchies()
        return {'success': True}
    except:
        return {'success': False}

@app.get("/current_remove_child")
def current_remove_child(uri=''):
    try:
        uri = uri.replace(path_home,'')
        api.remove_child(child=uri)
        parent = api.Initializer.storage.dataset
        parent = parent.replace(path_home,'')
        try:
            api.init(uri)
            api.connect_post_api()
            api.set_schema()
            api.remove_parent()
        except:
            pass
        api.init(parent)
        api.connect_post_api()
        api.set_schema()
        api.set_hierarchies()
        return {'success': True}
    except:
        return {'success': False}

@app.post("/merge")
async def merge_api(data: dict):
    # try:
    api.merge(father=data['father'], child=data['child'])
    api.commit(f"merged branch {data['child']} to {data['father']}")
    return {'success': True}
    # except:
    #     return {'success': False}

@app.get("/merge_child_to_master")
def merge_child_to_master_api(uri):
    try:
        master = api.Initializer.storage.dataset
        api.merge(father=master, child=uri)
        api.commit(f"merged branch {uri} to {master}")
        return {'success': True}
    except:
        return {'success': False}

@app.get("/merge_current_to_master")
def merge_current_to_master_api():
    # try:
    child = api.Initializer.storage.dataset
    hierarchy = api.get_hierarchy()
    if type(hierarchy['parent']) is str:
        if hierarchy['parent'] == '':
            return {'success': False}
        else:
            api.merge(father=hierarchy['parent'], child=child)
            api.commit(f"merged branch {child} to {hierarchy['parent']}")
            return {'success': True}
    # except:
    #     return {'success': False}

@app.get("/disconnect")
def disconnect_api(uri=''):
    try:
        try:
            api.init(uri)
            api.connect_post_api()
            api.set_schema()
            hierarchy = api.get_hierarchy()
            if len(hierarchy['children']) > 0:
                for child in hierarchy['children']:
                    api.remove_child(child=child)
                    try:
                        api.init(child)
                        api.connect_post_api()
                        api.set_schema()
                        api.remove_parent()
                    except:
                        pass
                api.init(uri)
                api.connect_post_api()
                api.set_schema()
            if type(hierarchy['parent']) is str:
                if hierarchy['parent'] != '':
                    assert(not '.stack' in hierarchy['parent'])
                    if path_home in hierarchy['parent']:
                        hierarchy['parent'] = hierarchy['parent'].replace(path_home,'')
                    try:
                        api.init(hierarchy['parent'])
                        api.connect_post_api()
                        api.set_schema()
                        api.remove_child(child=uri)
                    except:
                        pass
        except:
            pass
        api.set_hierarchies()
        return {'success': api.disconnect_dataset(uri)}
    except:
        api.set_hierarchies()
        return {'success': False}

@app.get("/get_datasets")
def get_datasets_api():
    try:
        return api.get_datasets()
    except:
        return {}

@app.get("/uri")
def uri_api():
    # try:
    return api.get_uri()
    # except:
    #     return {}

@app.get("/schema")
def schema_api():
    # try:
    return {'value': api.config['schema']}
    # except:
    #     return {'value': 'files'}

@app.get("/history")
def history_api():
    try:
        return api.history()
    except:
        return {}

@app.get('/set_schema')
def set_schema_api():
    api.set_schema()

@app.get('/reset_schema')
def reset_schema_api():
    api.reset_schema()
    return {'success': True}

@app.get('/add_tag')
def add_tag_api(file, tag):
    api.add_tag(file, tag)
    return {'success': True}

@app.get('/remove_tag')
def remove_tag_api(file, tag):
    api.remove_tag(file, tag)
    return {'success': True}

@app.get('/remove_all_tags')
def remove_all_tags_api(file):
    api.remove_all_tags(file)
    return {'success': True}

@app.post('/selection_add_tag')
def selection_add_tag_api(data: list):
    api.selection_add_tag(data[:-1], data[-1])
    return {'success': True}

@app.post('/selection_remove_all_tags')
def selection_remove_all_tags_api(data: list):
    api.selection_remove_all_tags(data)
    return {'success': True}

@app.get('/get_tags')
def get_tags_api(file):
    tags = api.get_tags(file)
    return tags

@app.post("/add_file/")
def add_file_api(file: UploadFile = File(description="A file read as UploadFile")):
    try:
        api.upload_file_binary(file.filename, file.file)
        api.commit('')
        return {'success': True}
    except:
        return {'success': False}

@app.post("/add_multifiles/")
def add_multifiles_api(files: list[UploadFile]):
    try:
        for file in files:
            api.upload_file_binary(file.filename, file.file)
        api.commit('')
        return {'success': True}
    except:
        return {'success': False}

@app.get("/get_embeddings")
def get_embeddings_api():
    return api.get_embeddings()

@app.get("/run_semantic_search")
def apply_semantic_search_api(prompt):
    return api.semantic_search(prompt)

@app.get("/commits_version")
def commits_version_api(version=1,l=5, page=0):
    try:
        return api.commits_version(version, l, page)
    except:
        return {}

@app.get("/key_versions")
def key_versions_api(key='',l=5, page=0):
    try:
        return api.key_versions(key, l, page)
    except:
        return {}

@app.get("/label_versions")
def label_versions_api(key='',l=5, page=0):
    try:
        return api.label_versions(key, l, page)
    except:
        return {}

@app.get("/last_n_commits")
def last_n_commits_api(n=5):
    try:
        return api.last_n_commits(n)
    except:
        return {}

@app.get("/last_commits_from_hist_api")
def last_commits_from_hist_api(n=1):
    try:
        return api.getHistoryCommits(n)
    except:
        return {}

@app.get("/status")
def status_api():
    # try:
    return api.status()
    # except:
    #     return {}

@app.get("/schema_metadata")
def schema_metadata_api():
    return api.schema_metadata()

@app.get("/current")
def current_api(page=0,max_pp=12):
    # try:
    full_json = api.status()
    idx_i = int(page)*int(max_pp)
    idx_f = (int(page)+1)*int(max_pp)

    current = {'keys': [], 'lm': [], 'len': len(full_json['keys'])}

    current['keys'] = full_json['keys'][idx_i:idx_f]
    current['lm'] = full_json['lm'][idx_i:idx_f]

    return current
    # except:
    #     return {'keys': {}, 'lm': {}}

@app.post("/set_filter/")
def set_filter_api(data: dict):
    return {'success': api.set_filters(data)}

@app.get("/reset_filters")
def reset_filter_api():
    return {'success': api.reset_filters()}

@app.get("/commit_req")
def commit_api(comment=''):
    return {'success': api.commit(comment)}

@app.get("/get_commit_metadata")
def get_commit_meta_api(commit):
    try:
        return api.load_commit_metadata(commit)
    except:
        return {}

@app.get("/pull_file_api")
def pull_file_api(file, version='current'):
    try:
        return StreamingResponse(api.load_file_binary(file, version), media_type="image/png")
    except:
        return Response(content='')

@app.get("/download_api")
def download_api():
    import io
    return StreamingResponse(io.BytesIO(api.download_files()),  media_type="application/x-zip-compressed", headers = { "Content-Disposition":f"attachment;filename=datapoints.zip"})

@app.get("/export_openai")
def export_openai_api():
    import io
    return StreamingResponse(io.BytesIO(api.export_openai()),  media_type="application/x-zip-compressed", headers = { "Content-Disposition":f"attachment;filename=datapoints.zip"})

@app.get("/set_bounding_boxes")
def set_bounding_boxes_api(val):
    try:
        return {'success': api.set_bounding_boxes(val)}
    except:
        return {'success': False}

@app.get("/get_thumbnail")
def get_thumbnail_api(file):
    try:
        import time
        t0 = time.time()
        thumb = api.load_thumbnail(file)
        print(f'time to thumbnail {time.time() - t0}s')
        return StreamingResponse(thumb, media_type="image/png")
    except:
        return Response(content='')

@app.get("/pull_csv_api")
def pull_csv_api(file, row_p=0, col_p=0, version='current'):
    try:
        data, _, _ = api.load_csv_binary(file, row_p, col_p, version)
        return StreamingResponse(data, media_type="image/png")
    except:
        return Response(content='')

@app.get("/pull_csv_metadata_api")
def pull_csv_metadata_api(file, version='current'):
    try:
        _, nr, nc = api.load_csv_binary(file, 0, 0, version)
        return {'rows': nr-1, 'cols': nc-1}
    except:
        return {'rows': 0, 'cols': 0}

@app.get("/remove_key")
def remove_key_api(key):
    try:
        api.remove(key)
        api.commit('')
        return {'sucess': True}
    except:
        return {'sucess': False}

@app.get("/remove_commit")
def remove_commit(version):
    try:
        api.remove_commit(version)
        api.commit('')
        return {'sucess': True}
    except:
        return {'sucess': False}

@app.get("/full_remove_key")
def full_remove_key_api(key):
    try:
        api.remove_full(key)
        api.commit('')
        return {'sucess': True}
    except:
        return {'sucess': False}

@app.get("/remove_key_version")
def remove_key_diff_api(key, version=-1):
    try:
        api.remove_key_diff(key, version)
        api.commit('')
        return {'sucess': True}
    except:
        return {'sucess': False}

@app.get("/get_csv_diff_metadata")
def get_csv_diff_metadata(key, v1='current', v2='current'):
    try:
        return api.load_csv_diff_metadata(key, v1, v2)
    except:
        return {}

@app.get("/get_csv_diff")
def get_csv_diff(key, v1='current', v2='current'):
    try:
        return api.load_csv_diff(key, v1, v2)
    except:
        return {}

@app.get("/revert_key_version")
def revert_key_version_api(key, version=-1, label='raw'):
    # try:
    api.revert_file(key, version)
    api.commit('reverted file ' + key)
    return {'sucess': True}
    # except:
    #     return {'sucess': False}

@app.get("/revert")
async def revert_api(version=0):
    # try:
    api.revert(version)
    api.commit('reverted dataset to version ' + version)
    return {'success': True}
    # except:
    #     return {'success': False}

@app.get("/get_prev_key")
def get_prev_key_api(key):
    return {'key': api.get_prev_key(key)}

@app.get("/get_next_key")
def get_next_key_api(key):
    return {'key': api.get_next_key(key)}

@app.get("/get_labels")
def get_labels_api(filename, version='current'):
    try:
        labels = api.get_labels(filename, version)
        print(labels)
        return labels
    except:
        return {}

@app.get("/diagnose")
def diagnose_api():
    # try:
    return api.detect_anomalies()

@app.get("/get_class_map")
def get_class_map_api():
    # try:
    print(api.get_class_map())
    return api.get_class_map()
    # except:
    #     return {}

@app.post("/set_class_map")
def set_class_map_api(data: dict):
    # try:
    return api.set_class_map(data)
    # except:
    #     return {}

@app.get("/get_colors")
def get_colors_api():
    # try:
    return api.get_color_map()
    # except:
    #     return {}

@app.post("/set_colors")
def set_colors_api(data: dict):
    # try:
    return api.set_color_map(data)
    # except:
    #     return {}

@app.post("/set_labels")
async def set_labels_api(data: dict):
    # try:
    return api.set_labels(data)
    # except:
    #     return {}

@app.post("/submit_label_per_user")
def submit_label_per_user_api(data: dict):
    # try:
    import io
    import urllib

    val = {'user': api.user, 'label': data}
    api.Initializer.storage.add_file_from_binary_global(api.Initializer.prefix_meta + '/submited_labels/' + urllib.parse.quote_plus(data['keyId']) + '/' + urllib.parse.quote_plus(f"{api.user}"),io.BytesIO(json.dumps(val).encode('ascii')))

    api.add_tag(data['keyId'], 'Please review')

    return {'success': True}
    # except:
    #     return {}

@app.get("/set_user")
def set_user_api(user, admin):
    api.user = user
    api.admin = admin
    return {'success': True}

@app.get("/get_user")
def get_user_api():
    try:
        return {'user': api.user, 'admin': 'True'}
    except:
        return {'user': '', 'admin': 'True'}

@app.get("/reset_label_per_user")
def reset_label_per_user_api(key):
    # try:
    import urllib
    keys, _ = api.Initializer.storage.load_list_in_path(api.Initializer.prefix_meta + '/submited_labels/' + urllib.parse.quote_plus(key) + '/' )
    arr = []
    for key in keys:
        api.Initializer.storage.remove_file_global(key)
    return {'success': True}

@app.get("/get_label_per_user")
def get_label_per_user_api(key):
    # try:
    import urllib
    keys, _ = api.Initializer.storage.load_list_in_path(api.Initializer.prefix_meta + '/submited_labels/' + urllib.parse.quote_plus(key) + '/' )
    arr = []
    for key in keys:
        val = json.load(api.Initializer.storage.load_file_global(key))
        arr.append(val)
    return arr
    # except:
    #     return {}

@app.get("/add_slice")
def add_slice(slice_name):
    return {'success': api.add_slice(slice_name=slice_name)}

@app.get("/remove_slice")
def remove_slice(slice_name):
    return {'success': api.remove_slice(slice_name=slice_name)}

@app.get("/reset_slices")
def reset_slices():
    return {'success': api.reset_slices()}

@app.post("/select_slice")
def select_slice(slices: list):
    return {'success': api.select_slices(slices=slices)}

@app.get("/get_slices")
def get_slices():
    try:
        return api.get_slices()
    except:
        return []

@app.get("/add_datapoint")
def add_datapoint(key):
    api.add_datapoint(key)
    return {'success': api.commit('added new datapoint')}

@app.get("/get_text")
def get_text(key, version='current'):
    return {'text': api.get_text(key, version)}

@app.post("/set_text")
def set_text(data: dict):
    api.set_text(data['key'], data['text'])
    api.commit(f"renamed key {data['key']} with {data['text']}")
    import hashlib
    return {'newKey': hashlib.md5(data['text'].encode('utf-8')).hexdigest()}

@app.get("/get_readme")
def get_readme():
    try:
        return Response(content=api.get_readme())
    except:
        return Response(content='')

# stacklib entry-points

@app.get("/init_experiment")
def init_experiment(data: dict):
    api.server_init_experiment(uri=data['uri'],project=data['project'])
    return {'success': True}

@app.post("/add_log")
def add_log(data: dict):
    api.server_add_log(data)
    return {'success': True}

@app.post("/get_models")
def get_models():
    return api.server_get_models()

@app.post("/add_model")
def add_model(data: Rate = Body(...), file: UploadFile = File(...)):
    api.server_upload_model(model=file.file, label=data.label)
    return {'success': True}

@app.post("/add_predictions")
def add_predictions(data: dict):
    return api.server_add_prediction(data)

@app.get("/get_model")
def get_model(data: dict):
    return StreamingResponse(api.server_get_model(data['label']))

@app.get("/logout_experiment")
def logout_experiment():
    api.server_logout_experiment()
    return {'success': True}

@app.get("/get_projects")
def get_projects():
    try:
        return api.get_projects()
    except:
        return []

@app.get("/remove_project")
def remove_project(project):
    return api.remove_project(project)

@app.get("/get_logs_list")
def get_logs_list(project):
    return api.get_logs(project)

@app.get("/get_logs_experiment")
def get_logs_experiment(log):
    return api.get_logs_experiment(log)

@app.post("/remove_log_experiment")
def remove_log_experiment(data: dict):
    return api.remove_log(data['experiment'],data['log'])

@app.get("/get_predictions_list")
def get_predictions_list(project):
    return api.get_predictions_list(project)

@app.get("/get_prediction")
def get_prediction(prediction):
    return api.get_prediction(prediction)