import json
import os
from PIL import Image
import plotly.graph_objects as go
import polars as pl
from typing import Dict, List, Tuple, Union

class BenetechDataset:
    def __init__(self, CFG):
        self.CFG = CFG
        self.annotations = self.get_annotations()

    def get_annotations(self):
        self.annotations = []
        for annotation_path in os.listdir(self.CFG.train_ann_path):
            with open(f"{self.CFG.train_ann_path}/{annotation_path}") as annotation_f:
                dct = json.load(annotation_f)
                dct['id'] = annotation_path.split('.')[0]
                self.annotations.append(dct)
        return self.annotations

    def to_pl_df(self):
        def flatten_dict(d: Dict, parent_key: str = '', sep: str = '_') -> Dict:
            """Flatten a nested dictionary"""
            items = []
            for k, v in d.items():
                new_key = f"{parent_key}{sep}{k}" if parent_key else k
                if isinstance(v, dict):
                    items.extend(flatten_dict(v, new_key, sep=sep).items())
                else:
                    items.append((new_key, v))
            return dict(items)

        data = []
        for dataaaa in self.annotations:
            # Flatten the nested dictionaries
            flat_data = flatten_dict(dataaaa)
            data.append(flat_data)
        df = pl.DataFrame(data)
        return df

    def get_chart_type_counts(self):
        chart_type_counts = {
            "dot": 0,
            "line": 0,
            "scatter": 0,
            "vertical_bar": 0,
            "horizontal_bar": 0
        }

        for annotation in self.annotations:
            chart_type_counts[annotation["chart-type"]] += 1

        return chart_type_counts

    def load_annotation(self, name: str):
        with open(f"{self.CFG.train_ann_path}/{name}.json") as annotation_f:
            ann_example = json.load(annotation_f)
        return ann_example

    def get_coords(self, polygon, img_height):
        xs = [
            polygon["x0"],
            polygon["x1"],
            polygon["x2"],
            polygon["x3"],
            polygon["x0"]
        ]

        ys = [
            -polygon["y0"] + img_height,
            -polygon["y1"] + img_height,
            -polygon["y2"] + img_height,
            -polygon["y3"] + img_height,
            -polygon["y0"] + img_height
        ]

        return xs, ys

    def add_line_breaks(self, text: str, break_num: int = 7) -> str:
        words = text.split()
        new_text = ""
        for i, word in enumerate(words, start=1):
            new_text += word
            if i % break_num == 0:
                new_text += "
"
            else:
                new_text += " "
        return new_text

    def get_tick_value(self, name, data_series):
        for el in data_series:
            if el["x"] == name:
                return el["y"]
            elif el["y"] == name:
                return el["x"]

    def plot_annotated_image(self, name: str, scale_factor: int = 1.0) -> None:
        img_example = Image.open(f"{self.CFG.train_img_path}/{name}.jpg")
        ann_example = self.load_annotation(name)

        # create figure
        fig = go.Figure()

        # constants
        img_width = img_example.size[0]
        img_height = img_example.size[1]

        # add invisible scatter trace
        fig.add_trace(
            go.Scatter(
                x=[0, img_width],
                y=[0, img_height],
                mode="markers",
                marker_opacity=0
            )
        )

        # configure axes
        fig.update_xaxes(
            visible=False,
            range=[0, img_width]
        )

        fig.update_yaxes(
            visible=False,
            range=[0, img_height],
            # the scaleanchor attribute ensures that the aspect ratio stays constant
            scaleanchor="x"
        )

        # add image
        fig.add_layout_image(dict(
            x=0,
            sizex=img_width,
            y=img_height,
            sizey=img_height,
            xref="x", yref="y",
            opacity=1.0,
            layer="below",
            sizing="stretch",
            source=img_example
        ))

        # add bounding box
        fig.add_shape(
            type="rect",
            x0=ann_example["plot-bb"]["x0"],
            y0=-ann_example["plot-bb"]["y0"] + img_height,
            x1=ann_example["plot-bb"]["x0"] + ann_example["plot-bb"]["width"],
            y1=-(ann_example["plot-bb"]["y0"] + ann_example["plot-bb"]["height"]) + img_height,
            line=dict(color="RoyalBlue"),
        )

        # add polygons
        for text in ann_example["text"]:
            name = text["text"]

            if text["role"] == "tick_label":
                tick_value = self.get_tick_value(name, ann_example["data-series"])
                if tick_value:
                    name = f'Text: {name}
Value: {tick_value}'

            xs, ys = self.get_coords(text["polygon"], img_height)
            fig.add_trace(go.Scatter(
                x=xs, y=ys, fill="toself",
                name=self.add_line_breaks(name),
                hovertemplate="%{name}",
                mode='lines'
            ))

        # add x-axis dots
        xs = [dot["tick_pt"]["x"] for dot in ann_example["axes"]["x-axis"]["ticks"]]
        ys = [-dot["tick_pt"]["y"] + img_height for dot in ann_example["axes"]["x-axis"]["ticks"]]
        fig.add_trace(go.Scatter(
            x=xs, y=ys, mode='markers',
            name="x-axis"
        ))

        # add y-axis dots
        xs = [dot["tick_pt"]["x"] for dot in ann_example["axes"]["y-axis"]["ticks"]]
        ys = [-dot["tick_pt"]["y"] + img_height for dot in ann_example["axes"]["y-axis"]["ticks"]]
        fig.add_trace(go.Scatter(
            x=xs, y=ys, mode='markers',
            name="y-axis"
        ))

        # configure other layout
        fig.update_layout(
            width=img_width * scale_factor,
            height=img_height * scale_factor,
            margin={"l": 0, "r": 0, "t": 0, "b": 0},
            showlegend=False
        )

        # disable the autosize on double click because it adds unwanted margins around the image
        # and finally show figure
        fig.show(config={'doubleClick': 'reset'})


import cv2
import numpy as np
import random
import pafy  # library to work with youtube videos
from recognition import process_number, recognize
from split_plate import split_plate, dumb_split_plate

# set url to grab video from youtube
url = 'https://www.youtube.com/watch?v=Li3FPoa3iYE'
url1 ='https://www.youtube.com/watch?v=DWo1ESaLg-Q'
num_set = set()  # to store read data
jobs = []
t_config = '--user-patterns pattern.txt --oem 3 --psm 13 -c tessedit_char_whitelist=-BDFGHJKLNPRSTUVXYZ0123456789  load_system_dawg=false load_freq_dawg=false'

# start parameters for masking
h_min = 8
h_max = 21
s_min = 112 #152
s_max = 205
v_min = 75 #195
v_max = 215 #244
confi = 0.8 # i need confidence no less than
pause = False
show_mask = False

# function runs as parameters changed

def set_mask(_):
    global lower, upper
    lower = np.array([cv2.getTrackbarPos("Hue_min", "params"), cv2.getTrackbarPos("Sat_min", "params"),
                      cv2.getTrackbarPos("Val_min", "params")])
    upper = np.array([cv2.getTrackbarPos("Hue_max", "params"), cv2.getTrackbarPos("Sat_max", "params"),
                      cv2.getTrackbarPos("Val_max", "params")])
    return ()

# define possible area size of a license plate
lp_max = 1000
lp_min = 400

counter = 0
tilt = 0  # if license plates are tilted, we need to fix it, set angle here (positive if the road turns right)

video = pafy.new(url)
best = video.getbest(preftype="mp4")

capture = cv2.VideoCapture()
capture.open(best.url)
s, img = capture.read()

# let's select roi
roi = cv2.selectROI('select', img)
cv2.destroyWindow('select')  # closing roi select window manually

# creating window to adjust parameters
cv2.namedWindow("params")
cv2.resizeWindow("params", 400, 200)
cv2.createTrackbar("Hue_min", "params", h_min, 178, set_mask)
cv2.createTrackbar("Hue_max", "params", h_max, 178, set_mask)
cv2.createTrackbar("Sat_min", "params", s_min, 255, set_mask)
cv2.createTrackbar("Sat_max", "params", s_max, 255, set_mask)
cv2.createTrackbar("Val_min", "params", v_min, 255, set_mask)
cv2.createTrackbar("Val_max", "params", v_max, 255, set_mask)

# building mask
lower = np.array([cv2.getTrackbarPos("Hue_min", "params"), cv2.getTrackbarPos("Sat_min", "params"),
                  cv2.getTrackbarPos("Val_min", "params")])
upper = np.array([cv2.getTrackbarPos("Hue_max", "params"), cv2.getTrackbarPos("Sat_max", "params"),
                  cv2.getTrackbarPos("Val_max", "params")])

# cropping image to roi
img = img[int(roi[1]):int(roi[1] + roi[3]), int(roi[0]):int(roi[0] + roi[2])]
min_diff = roi[2] * roi[3] / 5  # we skip the frame if it is changed in less pixels than min_diff

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
old_img_gray = np.copy(img_gray)

def t_recognize(img,c=0.3):  # function to ocr images
    save_ll=False
    #print ('splitting...')
    chars = dumb_split_plate(img)

    if save_ll:  # save pic
        for char in chars:
            cv2.imwrite('./ll/'+str(random.randint(0,1000000)) + ".png", char)

    if not chars:
        #print ('[main]:no chars')
        return False,0,0
    #print('[main]: returned chars:', len(chars))
    if len(chars) > 1:
        #print('processing...')
        nums = process_number(chars)
    else:
        #print ('less than one char')
        return False,0,0
    if len(nums) > 1:
        #print('recognizing...')
        try:
            t,conf = recognize(nums,c)

        except:
            #print('something went wrong')
            return False,0,0
        return t, conf, chars
    return False,0

# start main loop
while True:
    if not pause:  # if pause not pressed ('p' button)
        old_img_gray = np.copy(img_gray)
        s, img = capture.read()
        img = img[int(roi[1]):int(roi[1] + roi[3]), int(roi[0]):int(roi[0] + roi[2])]
        img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        k = np.sum(img_gray != old_img_gray)
        if k < min_diff:
            # skip if no significant changes
            continue

    if not s:  # no image captured - continue to next frame
        continue

    # processing image before searching for contours
    img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
    img_blur = cv2.blur(img_hsv, (10, 10), 2)
    img_eroded = cv2.erode(img_blur, (30, 30), iterations=2)
    mask = cv2.inRange(img_eroded, lower, upper)

    if show_mask: cv2.imshow('mask', mask)

    # detecting contours
    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    img_copy = np.copy(img)  # we need a copy to draw on it and show
    for cont in contours:
        area = cv2.contourArea(cont)

        if lp_max > area > lp_min:  # checking if area of contour within defined range
            box = cv2.approxPolyDP(cont, 1, 1)
            x, y, w, h = cv2.boundingRect(box)
            if h * w < 100:  # if area is way too small
                continue
            cv2.rectangle(img_copy, (x, y), (x + w, y + h), (255, 0, 0), 3)  # draw a box on copy

            number = img[y :y + h, x - 2:x + w]  # saving cropped license plate

            if 3 < (w / h) < 6:  # typical proportions of LP

                try:
                    cv2.imshow('params', number)
                except:
                    #print("error in contours detection, size is : ",number.shape)  # sometimes we get 0 in contour dimensions
                    continue
                if tilt != 0:  # fixing proportions if needed
                    pts1 = np.float32([[0, 0 + tilt], [number.shape[0], 0], [0, number.shape[1]],
                                       [number.shape[0], number.shape[1] - tilt]])
                    pts2 = np.float32(
                        [[0, 0], [number.shape[0], 0], [0, number.shape[1]], [number.shape[0], number.shape[1]]])

                    M = cv2.getPerspectiveTransform(pts1, pts2)
                    number = cv2.warpPerspective(number, M, (number.shape[1], number.shape[0]))
                text, conf, chars = t_recognize(number)  # run recognition

                if text and 3 < len(text) and conf > 0.6:
                    print('Detected license plate: ', text, "conf=",conf)
                    dummy=np.zeros((40,100,3))
                    if conf > confi:
                        c=int(conf*100)
                        cv2.putText(dummy, text, (0, 30), cv2.FONT_HERSHEY_PLAIN,1.3,(0,255,255),1 )
                        cv2.putText(dummy, str(c)+'%', (15, 15), cv2.FONT_HERSHEY_PLAIN, 1, (0, 255, 0), 1)
                        cv2.imshow('detected',dummy)

    cv2.imshow("Contours", img_copy)

    key = cv2.waitKey(1) & 0xFF
    if key == ord('s'):  # save pic
        cv2.imwrite("car" + str(counter) + ".png", img)
    elif key == ord('q'):  # stop
        break
    elif key == ord('z') and chars:  # save chars
        for char in chars:
            cv2.imwrite ('./ll/'+str(random.randint(0,1000000))+'.png',char)
        print ('[main]: Saved...')
    elif key == ord('m'):  # turn mask window on/off
        if show_mask:
            cv2.destroyWindow('mask')
        show_mask = not show_mask
    elif key == ord('p'):  # set on pause
        pause = not pause

capture.release()
cv2.destroyAllWindows()


# !pip3 install dit
# !pip3 install pyinform
# import dask_ml.model_selection as dcv
# from skopt import BayesSearchCV
# from skopt.space import Real, Categorical, Integer
# from hyperopt import hp,fmin,tpe,STATUS_OK,Trials
# import EEGExtract as eeg
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import accuracy_score
from sklearn.decomposition import PCA
from sklearn.feature_selection import chi2
from sklearn.feature_selection import SelectKBest, f_classif
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.feature_selection import *
from sklearn.model_selection import RandomizedSearchCV
from sklearn.model_selection import GridSearchCV
# from sklearn.ensemble import RandomForestRegressor
# import xgboost as xgb
import sys
import csv
import os
import math
import glob
from scipy import io,signal
import numpy as np
import pandas as pd

import pickle
from sklearn.metrics import mean_squared_error
from sklearn.impute import SimpleImputer

import matplotlib.pyplot as plt
# %matplotlib inline
import seaborn as sns
import copy
from sklearn import feature_selection
# from sklearn.ensemble import RandomForestClassifier
import argparse

# import cuml
# from cuml.svm import SVR
# from cuml.ensemble import RandomForestRegressor
# from cuml.svm import SVC
# from cuml.ensemble import RandomForestClassifier
# from cuml.metrics import  accuracy_score

#Import Machine Learning Algorithms
from sklearn.linear_model import LinearRegression
from sklearn.tree import DecisionTreeRegressor
from xgboost import XGBRegressor
from sklearn.neighbors import KNeighborsRegressor
from sklearn.svm import SVR
from sklearn.svm import SVC
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import RepeatedKFold
from sklearn.model_selection import GridSearchCV

# import joblib
# sys.modules['sklearn.externals.joblib'] = joblib

def loadFeaturesDict(dataset):
    featuresDict = {'shannonEntropy': None,
                'ShannonRes_delta':None,
                'ShannonRes_theta':None,
                'ShannonRes_alpha':None,
                'ShannonRes_beta':None,
                'ShannonRes_gamma':None,
                'HjorthComp':None,
                'HjorthMob':None,
                'falseNearestNeighbor':None,
                'medianFreq':None,
                'bandPwr_delta':None,
                'bandPwr_theta':None,
                'bandPwr_alpha':None,
                'bandPwr_beta':None,
                'bandPwr_gamma':None,
                'stdDev':None,
                'diffuseSlowing':None,
                'spikeNum':None,
                'deltaBurstAfterSpike':None,
                'shortSpikeNum':None,
                'numBursts':None,
                'burstLenMean':None,
                'burstLenStd':None,
                'numSuppressions':None,
                'suppLenMean':None,
                'suppLenStd':None,
                'dasm_delta': None,
                'dasm_theta': None,
                'dasm_alpha': None,
                'dasm_beta': None,
                'dasm_gamma': None,
                'rasm_delta': None,
                'rasm_theta': None,
                'rasm_alpha': None,
                'rasm_beta': None,
                'rasm_gamma': None,
                }

    # featurepath = os.getcwd() + '/' + dataset + '/data_extracted/featuresDict/'
    featurepath = os.getcwd() + '/Features/' + dataset + '/' #change

    featuresDict['shannonEntropy'] = np.load(featurepath + "shannonEntropy_1_1.npz", allow_pickle=True)['features']

    featuresDict['ShannonRes_delta'] = np.load(featurepath + "ShannonRes_sub_bands_delta_1_1.npz", allow_pickle=True)['features']

    featuresDict['ShannonRes_theta'] = np.load(featurepath + "ShannonRes_sub_bands_theta_1_1.npz", allow_pickle=True)['features']

    featuresDict['ShannonRes_alpha'] = np.load(featurepath + "ShannonRes_sub_bands_alpha_1_1.npz", allow_pickle=True)['features']

    featuresDict['ShannonRes_beta'] = np.load(featurepath + "ShannonRes_sub_bands_beta_1_1.npz", allow_pickle=True)['features']

    featuresDict['ShannonRes_gamma'] = np.load(featurepath + "ShannonRes_sub_bands_gamma_1_1.npz", allow_pickle=True)['features']

    #lyapunov
    # featuresDict['hFD'] = np.load(featurepath + d/DEAP_hFD.npy",allow_pickle=True)['features']

    featuresDict['HjorthComp'] = np.load(featurepath + "Hjorth_complexity_1_1.npz", allow_pickle=True)['features']

    featuresDict['HjorthMob'] = np.load(featurepath + "Hjorth_mobilty_1_1.npz",allow_pickle=True)['features']

    featuresDict['falseNearestNeighbor'] = np.load(featurepath + "falseNearestNeighbor_1_1.npz",allow_pickle=True)['features']

    featuresDict['medianFreq'] = np.load(featurepath + "medianFreq_1_1.npz",allow_pickle=True)['features']

    featuresDict['bandPwr_delta']=np.load(featurepath+"bandPwr_delta_1_1.npz", allow_pickle = True)['features']

    featuresDict['bandPwr_theta']=np.load(featurepath + "bandPwr_theta_1_1.npz", allow_pickle = True)['features']

    featuresDict['bandPwr_alpha']=np.load(featurepath + "bandPwr_alpha_1_1.npz", allow_pickle = True)['features']

    featuresDict['bandPwr_beta']=np.load(featurepath + "bandPwr_beta_1_1.npz", allow_pickle = True)['features']

    featuresDict['bandPwr_gamma']=np.load(featurepath + "bandPwr_gamma_1_1.npz", allow_pickle = True)['features']

    featuresDict['stdDev'] = np.load(featurepath + "stdDev_1_1.npz",allow_pickle=True)['features']

    # featuresDict['regularity'] = np.load(featurepath + "",allow_pickle=True)['features']

    # featuresDict['volt05'] = np.load(featurepath + "",allow_pickle=True)['features']
    # featuresDict['volt10'] = np.load(featurepath + "",allow_pickle=True)['features']
    # featuresDict['volt20'] = np.load(featurepath + "",allow_pickle=True)['features']

    featuresDict['diffuseSlowing'] = np.load(featurepath + "diffuseSlowing_1_1.npz",allow_pickle=True)['features']

    featuresDict['spikeNum'] = np.load(featurepath + "spikeNum_1_1.npz",allow_pickle=True)['features']

    featuresDict['deltaBurstAfterSpike'] = np.load(featurepath + "deltaBurstAfterSpike_1_1.npz",allow_pickle=True)['features']

    featuresDict['shortSpikeNum'] = np.load(featurepath + "shortSpikeNum_1_1.npz", allow_pickle=True)['features']

    featuresDict['numBursts'] = np.load(featurepath + "numBursts_1_1.npz",allow_pickle=True)['features']

    featuresDict['burstLenMean'] = np.load(featurepath + "burstLen_u_and_sigma_mean_1_1.npz",allow_pickle=True)['features']

    featuresDict['burstLenStd'] = np.load(featurepath + "burstLen_u_and_sigma_std_1_1.npz",allow_pickle=True)['features']

    # featuresDict['burstBandPowers'] = np.load(featurepath + "",allow_pickle=True)['features']

    featuresDict['numSuppressions'] = np.load(featurepath + "numSuppressions_1_1.npz",allow_pickle=True)['features']

    featuresDict['suppLenMean'] = np.load(featurepath + "suppressionLen_u_and_sigma_mean_1_1.npz",allow_pickle=True)['features']

    featuresDict['suppLenStd'] = np.load(featurepath + "suppressionLen_u_and_sigma_std_1_1.npz",allow_pickle=True)['features']

    featuresDict['dasm_delta'] = np.load(featurepath + "dasm_delta_1_1.npz",allow_pickle=True)['features']
    featuresDict['dasm_theta'] = np.load(featurepath + "dasm_theta_1_1.npz",allow_pickle=True)['features']
    featuresDict['dasm_alpha'] = np.load(featurepath + "dasm_alpha_1_1.npz",allow_pickle=True)['features']
    featuresDict['dasm_beta'] = np.load(featurepath + "dasm_beta_1_1.npz",allow_pickle=True)['features']
    featuresDict['dasm_gamma'] = np.load(featurepath + "dasm_gamma_1_1.npz",allow_pickle=True)['features']

    featuresDict['rasm_delta'] = np.load(featurepath + "rasm_delta_1_1.npz",allow_pickle=True)['features']
    featuresDict['rasm_theta'] = np.load(featurepath + "rasm_theta_1_1.npz",allow_pickle=True)['features']
    featuresDict['rasm_alpha'] = np.load(featurepath + "rasm_alpha_1_1.npz",allow_pickle=True)['features']
    featuresDict['rasm_beta'] = np.load(featurepath + "rasm_beta_1_1.npz",allow_pickle=True)['features']
    featuresDict['rasm_gamma'] = np.load(featurepath + "rasm_gamma_1_1.npz",allow_pickle=True)['features']

    return featuresDict

params_dict = {
    str(type(DecisionTreeRegressor()).__name__) : {
           "splitter":["best","random"],
           "max_depth" : [1,3,5,7,9,11,12],
           "min_samples_leaf":[1,2,3,4,5,6,7,8,9,10],
           "min_weight_fraction_leaf":[0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9],
           "max_features":["auto","log2","sqrt",None],
           "max_leaf_nodes":[None,10,20,30,40,50,60,70,80,90] },
    str(type(SVR()).__name__) : {
            'kernel' : ('linear', 'poly', 'rbf', 'sigmoid'),
            'C' : [1,5,10],
            'degree' : [3,8],
            'coef0' : [0.01,10,0.5],
            'gamma' : ('auto','scale')},
    str(type(RandomForestRegressor()).__name__) : {
            'bootstrap': [True],
            'max_depth': [80, 90, 100, 110],
            'max_features': [2, 3],
            'min_samples_leaf': [3, 4, 5],
            'min_samples_split': [8, 10, 12],
            'n_estimators': [100, 200, 300, 1000]
    },
    str(type(XGBRegressor()).__name__) : {
            'learning_rate': [0.01, 0.1],
            'max_depth': [3, 7, 10],
            'min_child_weight': [1, 3, 5],
            'subsample': [0.5, 0.7],
            'colsample_bytree': [0.5, 0.7],
            'n_estimators' : [100, 200, 500],
            'objective': ['reg:squarederror']
    },
    str(type(KNeighborsRegressor()).__name__) : {
            'n_neighbors': [2,3,4,5,6],
            'weights': ['uniform','distance']},

}


import sqlite3
import shutil

from PyQt5.QtWidgets import QMainWindow
from designers.admin_add_dog_window_designer import Ui_AdminAddDogWindow
from PyQt5.QtWidgets import QFileDialog
from functions.convert_to_png import *

class AddDogWidget(QMainWindow, Ui_AdminAddDogWindow):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.setWindowTitle("add")
        self.btn_add.clicked.connect(self.add)
        self.btn_file.clicked.connect(self.file)

    def add(self):
        try:
            con = sqlite3.connect("dog_shelter_db")
            cur = con.cursor()
            breed = self.breed_edit.text()
            gender = self.gender_edit.text()
            filename = self.filename_edit.text()

            breed_id = cur.execute("""SELECT id FROM breeds
                WHERE breed == :breed""", {'breed': breed}).fetchone()[0]

            cur.execute("""INSERT INTO
                dogs(dog_image_file_name, breed_id, gender, is_taken)
                VALUES(:filename, :breed_id, :gender, "no")
                """, {'filename': filename, 'gender': gender, 'breed_id': breed_id})

            con.commit()
            con.close()
            self.hide()
        except TypeError:
            self.lbl_error.setText("Введите породу и пол собаки")
        except sqlite3.IntegrityError:
            self.lbl_error.setText("Файл с таким именем уже существует. Возможно, "
                                   "Вы не выбрали файл с картинкой")

    def file(self):
        filename = self.filename_edit.text()
        open(f"images\{filename}.png", "x")  # создание нового файла в images
        inp_file_name = QFileDialog.getOpenFileName(self, 'Выбрать картинку', '')[0]
        shutil.copy(inp_file_name, f"images\{filename}.png")  # перенос файла в images
        convert_to_png(filename)  # конвертирование файла с картинкой в png


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

from openerp import models, fields, api
import logging
from datetime import datetime, timedelta, date
import requests

_logger = logging.getLogger(__name__)

URL_OPERATIONS = 'https://api.mobbex.com/p/entity/operations'

class ExtendsResCompany(models.Model):
	_name = 'res.company'
	_inherit = 'res.company'

	mobbex_id = fields.Many2one('financiera.mobbex.config', 'Configuracion Mobbex')

	@api.one
	def mobbex_update_aprobados(self):
		if self.mobbex_id:
			headers = {
				'x-api-key': self.mobbex_id.api_key,
				'x-access-token': self.mobbex_id.access_token,
			}
			from_day = datetime.now() - timedelta(days=self.mobbex_id.days_check_update_aprobados)
			created = datetime.now()
			page = 0
			while (from_day < created):
				params = {
					'page': page,
					'limit': 50,
					'status': 200,
				}
				r = requests.get(URL_OPERATIONS, params=params, headers=headers)
				print("r", r)
				print("r.status_code", r.status_code)
				response = r.json()
				print("response", response)
				if 'result' in response and response['result'] == True and 'data' in response:
					print('result')
					data = response['data']
					if 'docs' in data:
						print('docs')
						docs = data['docs']
						for doc in docs:
							if 'reference' in doc:
								created = datetime.strptime(doc['created'].split('T')[0], "%Y-%m-%d")
								_id = doc['reference'].split('_')[0]
								if doc['context']['value'] == 'plugin.value.subscriptions:exec':
									cuota_id = self.env['financiera.prestamo.cuota'].sudo().browse(int(_id))
									if cuota_id.state == 'activa':
										cuota_id.mobbex_read_execution_aprobado(doc)
										_logger.info('Mobbex: nuevo debito procesado.')
								elif doc['context']['value'] == 'plugin.value.payment_order:web':
									orden_pago_id = self.env['financiera.mobbex.orden.pago'].sudo().browse(int(_id))
									if orden_pago_id.state != 'cobrada':
										orden_pago_id.mobbex_orden_pago_read_execution_aprobado(doc)
										_logger.info('Mobbex: nueva orden de pago procesada.')
							else:
								_logger.warning('Mobbex: No existe reference de cuota.')
							if from_day >= created:
								break
						if len(docs) <= 1:
							break
					else:
						break
				else:
					break
				page += 1


#!/usr/bin/env python

from .periodictable import PeriodicTable
from .atomgroup import AtomGroup
from .atom import Atom
from .position import Position
import logging
logger = logging.getLogger(__name__)

class SimpleGro(object):
    """
    Simple .gro file

    sample:
    MD of 2 waters, t= 0.0
        6
        1WATER  OW1    1   0.126   1.624   1.679  0.1227 -0.0580  0.0434
        1WATER  HW2    2   0.190   1.661   1.747  0.8085  0.3191 -0.7791
        1WATER  HW3    3   0.177   1.568   1.613 -0.9045 -2.6469  1.3180
        2WATER  OW1    4   1.275   0.053   0.622  0.2519  0.3140 -0.1734
        2WATER  HW2    5   1.337   0.002   0.680 -1.0641 -1.1349  0.0257
        2WATER  HW3    6   1.326   0.120   0.568  1.9427 -0.8216 -0.0244
    1.82060   1.82060   1.82060
    """

    def __init__(self):
        self._title = ""
        self._num_of_atoms = 0
        self._atoms = []

    def load(self, gro_filepath):
        with open(gro_filepath, "r") as f:
            # line 1
            line = f.readline()
            line = line.rstrip()
            self._title = line

            # line 2
            line = f.readline()
            line = line.rstrip()
            self._num_of_atoms = int(line)

            # atom lines
            for i in range(self._num_of_atoms):
                line = f.readline()
                line = line.rstrip()

                residue_number = int(line[0:5])
                residue_name = line[5:10].strip()
                atom_name = line[10:15].strip()
                atom_number = int(line[15:20])
                # position (in nm, x y z in 3 columns, each 8 positions with 3 decimal places)
                position_x = float(self._str2float(line[20:28]))
                position_y = float(self._str2float(line[28:36]))
                position_z = float(self._str2float(line[36:44]))
                # velocity (in nm/ps (or km/s), x y z in 3 columns, each 8 positions with 4 decimal places)
                velocity_x = float(self._str2float(line[44:52]))
                velocity_y = float(self._str2float(line[52:60]))
                velocity_z = float(self._str2float(line[60:68]))

                atom_data = (residue_number, residue_name, atom_name, atom_number,
                             position_x, position_y, position_z,
                             velocity_x, velocity_y, velocity_z)
                # print(atom_data)
                self._atoms.append(atom_data)

            # box vectors
            line = f.readline()
            line = line.strip()
            box_vectors = line.split()
            box_vectors = [float(x) for x in box_vectors]
            for i in range(len(box_vectors), 6):
                box_vectors.append(0.0)
            self._box_vectors = box_vectors

    def _str2float(self, str):
        if len(str) == 0:
            return 0.0
        else:
            return float(str)

    def get_atomgroup(self):
        pt = PeriodicTable()
        output = AtomGroup()
        output.name = self._title

        model = AtomGroup()
        chain = AtomGroup()

        current_res_id = -1
        current_ag = None
        for atom_data in self._atoms:
            (res_id, res_name, name, id, x, y, z, vx, vy, vz) = atom_data
            if current_res_id != res_id:
                if current_ag != None:
                    chain.set_group(current_res_id, current_ag)
                current_res_id = res_id
                current_ag = AtomGroup()
                current_ag.name = res_name

            atom = Atom()
            name = name.strip()
            atom.name = name

            symbol = ""
            if len(name) == 1:
                symbol = name
            else:
                name2 = name[0:2]
                if name2 in pt:
                    symbol = name2
                else:
                    symbol = name[0]
            atom.symbol = symbol
            atom.position = Position(
                x * 10.0, y * 10.0, z * 10.0)  # nm -> angstrom
            current_ag.set_atom(id, atom)

        if current_ag != None:
            chain.set_group(current_res_id, current_ag)
            model.set_group("_", chain)
            output.set_group(1, model)

        return output

    def set_by_atomgroup(self, atomgroup):
        assert(isinstance(atomgroup, AtomGroup))

        self._title = atomgroup.name
        self._num_of_atoms = atomgroup.get_number_of_atoms()
        self._atoms = []

        #count = 0
        serial = 1
        residue_index = 1
        for model_key, model in atomgroup.groups():
            for chain_id, chain in model.groups():
                for res_key, residue in chain.groups():
                    residue_number = residue_index
                    residue_index += 1
                    residue_name = residue.name
                    for key, atom in residue.atoms():
                        atom_name = atom.name
                        atom_number = serial
                        serial += 1
                        position_x = atom.xyz.x * 0.1  # angstrom -> nm
                        position_y = atom.xyz.y * 0.1
                        position_z = atom.xyz.z * 0.1
                        velocity_x = 0.0
                        velocity_y = 0.0
                        velocity_z = 0.0
                        self._atoms.append((residue_number, residue_name, atom_name, atom_number,
                                            position_x, position_y, position_z,
                                            velocity_x, velocity_y, velocity_z))
                        #count += 1

        (pos1, pos2) = atomgroup.box()
        # the vdw radii of "C" = 1.96
        self._box_vectors = (abs(pos2.x - pos1.x),
                             abs(pos2.y - pos1.y), abs(pos2.z - pos1.z))

    def __str__(self):
        answer = ""
        answer += "{}\n".format(self._title)
        answer += "{}\n".format(len(self._atoms))
        for i in range(len(self._atoms)):
            residue_number = int(self._atoms[i][0] % 10000)
            residue_name = self._atoms[i][1][0:5]
            atom_name = self._atoms[i][2][0:5]
            atom_number = int(self._atoms[i][3] % 10000)
            position_x = self._atoms[i][4]
            position_y = self._atoms[i][5]
            position_z = self._atoms[i][6]
            velocity_x = self._atoms[i][7]
            velocity_y = self._atoms[i][8]
            velocity_z = self._atoms[i][9]

            answer += "{:>5}{:<5}{:>5}{:>5}{:8.3f}{:8.3f}{:8.3f}{:8.4f}{:8.4f}{:8.4f}\n".format(
                residue_number, residue_name, atom_name, atom_number,
                position_x, position_y, position_z,
                velocity_x, velocity_y, velocity_z)
        answer += " ".join(map(str, self._box_vectors))

        return answer


from transformers import BertTokenizer
from transformers import BertModel
from torch.nn import Softmax
import torch
import matplotlib.pyplot as plt

# 设计思想, 高计算量操作尽量减少, 对齐问题解决思路要清晰
# 一次句子分析, 多个函数共享
# 统一用torch.tensor表征所有容器

tokenizer = BertTokenizer.from_pretrained('bert-base-uncased')
model = BertModel.from_pretrained('bert-base-uncased')

class sent_analyzer:
	def __init__(self, sent):
		self.raw_text = sent.strip() # str
		self.space_tokenization = sent.split(sep=' ')  # [str, str]
		self.raw_text_lower = self.raw_text.lower() # str
		self.space_tokenization_lower = [i.lower() for i in self.space_tokenization] # [str, str]
		self.bert_tokenization_obj = tokenizer(self.raw_text_lower, return_tensors='pt') # {key:tensor, key:tensor}
		self.bert_tokenization_ids = self.bert_tokenization_obj['input_ids'][0].tolist() # [int, int]
		self.bert_tokenization_wordpieces = tokenizer.convert_ids_to_tokens(self.bert_tokenization_ids)  # [str,str]
		self.bert_tokenization_wordpieces_nosep = self.bert_tokenization_wordpieces[1:-1] # [str, str]
		self.bert_tokenization_ids_nosep = self.bert_tokenization_ids[1:-1] # [int, int]
		self.bert_model_return = model(**self.bert_tokenization_obj, output_hidden_states=True, output_attentions=True) # (tensor, tensor, tuple, typle) # (last_hidden_state, pooler_output, hidden_states, attentions)
		self.bert_last_hidden_state = self.bert_model_return[0].squeeze() # tensor
		self.bert_hidden_states = torch.stack(self.bert_model_return[2][1:],axis=0).squeeze() # tensor
		self.bert_attentions = torch.stack(self.bert_model_return[3],axis=0).squeeze() # tensor
		self.bert_attentions_nosep = self.bert_attentions[:,:,1:-1,1:-1] # tensor
		self.bert_attentions_nosep_linscale = self.bert_attentions_nosep/self.bert_attentions_nosep.sum(axis=-1).unsqueeze(-1) # tensor
		self.bert_attentions_nosep_softmaxscale = Softmax(dim=-1)(self.bert_attentions_nosep) # tensor
		self.space_wordpiece_posmap = self.wordpiece_mapping(self.space_tokenization_lower) # {int:[int,int], int:[int,int]}
		self.reduced_attention = self.reduced_attention_nosep_linscale(self.space_tokenization_lower) # tensor

	def wordpiece_mapping(self,target_tokens):
		'''[int,int]'''
		ud_sent = target_tokens
		wp_sent = self.bert_tokenization_wordpieces_nosep
		ud_cnt = 0
		wp_cnt = 0
		wp_buffer = []
		idmap_list = []
		while True:
			try:
				ud_pop = ud_sent[ud_cnt]
				wp_pop = wp_sent[wp_cnt]
				if ud_pop == wp_pop:
					idmap_list.append(ud_cnt)
					ud_cnt += 1
					wp_cnt += 1
				else:
					wp_buffer.append(wp_pop.replace('##',''))
					idmap_list.append(ud_cnt)
					if ''.join(wp_buffer) != ud_pop:
						wp_cnt += 1
					else:
						wp_cnt += 1
						ud_cnt += 1
						wp_buffer = []
			except IndexError:
				break
		idmap_dict = dict()
		for i in range(max(idmap_list)+1):
			idmap_dict[i] = [idx for idx,j in enumerate(idmap_list) if j==i]
		return idmap_dict

	def reduced_attention_nosep_linscale(self,target_tokens):
		posmap = self.wordpiece_mapping(self.space_tokenization_lower)
		num_rows = len(posmap.keys())
		num_cols = sum([len(posmap[x]) for x in posmap if isinstance(posmap[x], list)])
		row_reduced_attention = torch.empty(12,12,num_rows,num_cols)
		row_col_reduced_attention = torch.empty(12,12,num_rows,num_rows)
		for lay in range(12):
			for head in range(12):
				for pair in posmap.items():
					row_reduced_attention[lay][head][pair[0]] = (torch.index_select(self.bert_attentions_nosep_linscale[lay][head], -2, torch.tensor(pair[1])).sum(axis=-2))/len(pair[1])
		for lay in range(12):
			for head in range(12):
				for pair in posmap.items():
					row_col_reduced_attention[lay][head][:,pair[0]] = torch.index_select(row_reduced_attention[lay][head], -1, torch.tensor(pair[1])).sum(axis=-1)
		return row_col_reduced_attention

	def viz_bert_attentions(self,lay,head):
		fig = plt.figure()
		ax = fig.subplots()
		data = self.bert_attentions[lay][head].detach().numpy()
		gcf = ax.matshow(data,cmap='Greens')
		ax.set_xticks(range(data.shape[0]))
		ax.set_yticks(range(data.shape[1]))
		xticklabels = [str(i)+' '+j for i,j in zip(range(data.shape[0]), self.bert_tokenization_wordpieces)]
		yticklabels = [j+' '+str(i) for i,j in zip(range(data.shape[0]), self.bert_tokenization_wordpieces)]
		ax.set_xticklabels(xticklabels,rotation=45, ha='left')
		ax.set_yticklabels(yticklabels)
		ax.set_xlabel(f'Layer-{lay+1}, Head-{head+1}')
		bar = plt.gcf().colorbar(gcf)
		plt.show()
		plt.close()
		return

	def viz_bert_attentions_nosep_linscale(self,lay,head):
		fig = plt.figure()
		ax = fig.subplots()
		data = self.bert_attentions_nosep_linscale[lay][head].detach().numpy()
		gcf = ax.matshow(data,cmap='Greens')
		ax.set_xticks(range(data.shape[0]))
		ax.set_yticks(range(data.shape[1]))
		ax.set_xticklabels([str(i)+' '+j for i,j in zip(range(data.shape[0]), self.bert_tokenization_wordpieces_nosep)], rotation=45)
		ax.set_yticklabels([j+' '+str(i) for i,j in zip(range(data.shape[0]), self.bert_tokenization_wordpieces_nosep)])
		bar = plt.gcf().colorbar(gcf)
		plt.show()
		plt.close()
		return

	def viz_bert_attentions_nosep_softmaxscale(self,lay,head):
		fig = plt.figure()
		ax = fig.subplots()
		data = self.bert_attentions_nosep_softmaxscale[lay][head].detach().numpy()
		gcf = ax.matshow(data,cmap='Greens')
		ax.set_xticks(range(data.shape[0]))
		ax.set_yticks(range(data.shape[1]))
		ax.set_xticklabels([str(i)+' '+j for i,j in zip(range(data.shape[0]), self.bert_tokenization_wordpieces_nosep)], rotation=45)
		ax.set_yticklabels([j+' '+str(i) for i,j in zip(range(data.shape[0]), self.bert_tokenization_wordpieces_nosep)])
		bar = plt.gcf().colorbar(gcf)
		plt.show()
		plt.close()
		return

	def viz_bert_attentions_nosep_linscale_reduced(self,lay,head):
		fig = plt.figure()
		ax = fig.subplots()
		data = self.reduced_attention[lay][head].detach().numpy()
		gcf = ax.matshow(data,cmap='Greens')
		ax.set_xticks(range(data.shape[0]))
		ax.set_yticks(range(data.shape[1]))
		ax.set_xticklabels([str(i)+' '+j for i,j in zip(range(data.shape[0]), self.space_tokenization)], rotation=45)
		ax.set_yticklabels([j+' '+str(i) for i,j in zip(range(data.shape[0]), self.space_tokenization)])
		bar = plt.gcf().colorbar(gcf)
		plt.show()
		plt.close()

sent = 'mary had a little lamb, its fleece was white as snow'

sent_obj = sent_analyzer(sent)

print('done')


import ldap
import ldif
import sys
import os
from lib389._constants import DIRSRV_STATE_ONLINE, DSRC_CONTAINER

MAJOR, MINOR, _, _, _ = sys.version_info

if MAJOR >= 3:
    import configparser
else:
    import ConfigParser as configparser

# Read the paths from default.inf

# Create a lazy eval class for paths. When we first access, we re-read
# the inf. This way, if we never request a path, we never need to read
# this file. IE remote installs, we shouldn't need to read this.

# Could this actually become a defaults module, and merge with instance/options?
# Would it handle the versioning requirements and diff we need?

DEFAULTS_PATH = [
    '/usr/share/dirsrv/inf/defaults.inf',
    '/usr/local/share/dirsrv/inf/defaults.inf',
    '/opt/dirsrv/share/dirsrv/inf/defaults.inf',
    '/opt/local/share/dirsrv/inf/defaults.inf',
    '/opt/share/dirsrv/inf/defaults.inf',
]

MUST = [
    'product',
    'version',
    'user',
    'group',
    'root_dn',
    'prefix',
    'bin_dir',
    'sbin_dir',
    'lib_dir',
    'data_dir',
    'tmp_dir',
    'sysconf_dir',
    'config_dir',
    'schema_dir',
    'cert_dir',
    'local_state_dir',
    'run_dir',
    'lock_dir',
    'log_dir',
    'inst_dir',
    'db_dir',
    'db_home_dir',
    'backup_dir',
    'ldif_dir',
    'initconfig_dir',
    'tmpfiles_d',
]

# will need to add the access, error, audit log later.

# This maps a config to (entry, attr).
# This can be used online, or while the server is offline and we can parse dse.ldif

CONFIG_MAP = {
    'user' : ('cn=config', 'nsslapd-localuser'),
    'group' : ('cn=config','nsslapd-localuser'), # Is this correct?
    'schema_dir' : ('cn=config','nsslapd-schemadir'),
    'cert_dir' : ('cn=config','nsslapd-certdir'),
    'lock_dir' : ('cn=config','nsslapd-lockdir'),
    'inst_dir' : ('cn=config','nsslapd-instancedir'),
    'db_dir' : ('cn=config,cn=ldbm database,cn=plugins,cn=config', 'nsslapd-directory'),
    'db_home_dir' : ('cn=bdb,cn=config,cn=ldbm database,cn=plugins,cn=config', 'nsslapd-db-home-directory'),
    'backup_dir': ('cn=config','nsslapd-bakdir'),
    'ldif_dir': ('cn=config','nsslapd-ldifdir'),
    'error_log' : ('cn=config', 'nsslapd-errorlog'),
    'access_log' : ('cn=config', 'nsslapd-accesslog'),
    'audit_log' : ('cn=config', 'nsslapd-auditlog'),
    'security_log' : ('cn=config', 'nsslapd-securitylog'),
    'ldapi': ('cn=config', 'nsslapd-ldapifilepath'),
    'version': ('', 'vendorVersion'),
}

#Alternate map if attribute is not found in CONFIG_MAP

CONFIG_MAP2 = {
    'db_home_dir' : ('cn=config,cn=ldbm database,cn=plugins,cn=config', 'nsslapd-db-home-directory'),
}

DSE_MAP = {
    'nsslapd-bakdir': 'backup_dir',
    'nsslapd-schemadir': 'schema_dir',
    'nsslapd-certdir': 'cert_dir',
    'nsslapd-lockdir': 'lock_dir',
    'nsslapd-ldifdir': 'ldif_dir',
    'nsslapd-bakdir': 'backup_dir',
    'nsslapd-errorlog': 'error_log',
    'nsslapd-accesslog': 'access_log',
    'nsslapd-auditlog': 'audit_log',
    'nsslapd-securitylog': 'security_log',
    'nsslapd-ldapifilepath': 'ldapi',
    'nsslapd-instancedir': 'inst_dir',
}

SECTION = 'slapd'

class Paths(object):
    def __init__(self, serverid=None, instance=None, local=True):
        """
        Parses and uses a set of default paths from wellknown locations. The list
        of keys available is from the MUST attribute in this module.

        To use this module:

        p = Paths()
        p.bindir

        If the defaults.inf is NOT in a wellknown path, this will throw IOError
        on the first attribute access. If this does not have a value defaults.inf
        it will raise KeyError that the defaults.inf is not capable of supporting
        this tool.

        This is lazy evaluated, so the file is read at the "last minute" then
        the contents are cached. This means that remote tools that don't need
        to know about paths, shouldn't need to have a copy of 389-ds-base
        installed to remotely admin a server.
        """
        self._is_container = os.path.exists(DSRC_CONTAINER)
        self._defaults_cached = False
        self._config = None
        self._serverid = serverid
        self._instance = instance
        self._islocal = local

    def _get_defaults_loc(self, search_paths):
        ## THIS IS HOW WE HANDLE A PREFIX INSTALL
        prefix = os.getenv('PREFIX')
        # When we run 389-ds in Ansible, its processing sets PREFIX to "", so we should check for both - None and ""
        if prefix:
            spath = os.path.join(prefix, 'share/dirsrv/inf/defaults.inf')
            if os.path.isfile(spath):
                return spath
            else:
                raise IOError('defaults.inf not found in prefixed location %s' % spath)
        for spath in search_paths:
            if os.path.isfile(spath):
                return spath
        raise IOError('defaults.inf not found in any well known location!')

    def _read_defaults(self):
        spath = self._get_defaults_loc(DEFAULTS_PATH)
        self._config = configparser.ConfigParser()
        self._config.read([spath])
        if self._is_container:
            # Load some values over the top that are container specific
            self._config.set(SECTION, "pid_file", "/data/run/slapd-localhost.pid")
            self._config.set(SECTION, "ldapi", "/data/run/slapd-localhost.socket")
        self._defaults_cached = True

        # Now check the dse.ldif (if present) to see if custom paths were set
        if self._serverid:
            # Get the dse.ldif from the instance name
            prefix = os.environ.get('PREFIX', ""),
            if self._serverid.startswith("slapd-"):
                self._serverid = self._serverid.replace("slapd-", "", 1)
            dsepath = "{}/etc/dirsrv/slapd-{}/dse.ldif".format(prefix[0], self._serverid)
        elif self._instance is not None:
            ds_paths = Paths(self._instance.serverid, None)
            dsepath = os.path.join(ds_paths.config_dir, 'dse.ldif')
        else:
            # Nothing else to do but return
            return

        try:
            from lib389.utils import ensure_str  # prevents circular import errors
            with open(dsepath, 'r') as file_dse:
                dse_parser = ldif.LDIFRecordList(file_dse, max_entries=2)
                if dse_parser is None:
                    return
                dse_parser.parse()
                if dse_parser.all_records is None:
                    return
                # We have the config, start processing the DSE_MAP
                config = dse_parser.all_records[1]  # cn=config
                attrs = config[1]
                for attr in DSE_MAP.keys():
                    if attr in attrs.keys():
                        self._config.set(SECTION, DSE_MAP[attr], ensure_str(attrs[attr][0]))
        except:
            # No dse.ldif or can't read it, no problem just skip it
            pass

    def _validate_defaults(self):
        if self._defaults_cached is False:
            return False
        for k in MUST:
            if self._config.has_option(SECTION, k) is False:
                raise KeyError('Invalid defaults.inf, missing key %s' % k)
        return True

    def _pretty_exception(self, err, msg):
        # Remap LDAPError exceptions to get a nicer stack than python-ldap one
        # Lets grab the data from the exception (a bit painfull but I did not find any better way)
        result = None
        desc = None
        info = None
        for e in err.args:
            if "result" in e:
                result = e["result"]
            if "desc" in e:
                desc = e["desc"]
            if "info" in e:
                info = e["info"]
        if result is None or desc is None:
            # keep original exception in unusual cases
            return (err)
        # Lets create a new exception (with same class) to have current stack without the python-ldap internal stack
        # And to provide more relevant info that are useful for debug
        info = f"{msg}.\nAdditionnal info is: {info}"
        return (err.__class__({ "result":result, "desc":desc, "info":info}))

    def __getattr__(self, name):
        from lib389.utils import ensure_str
        if self._defaults_cached is False and self._islocal:
            self._read_defaults()
            self._validate_defaults()
        # Are we online? Is our key in the config map?
        while name in CONFIG_MAP and self._instance is not None and self._instance.state == DIRSRV_STATE_ONLINE:
            # Get the online value.
            err = None
            try:
                (dn, attr) = CONFIG_MAP[name]
                ent = self._instance.getEntry(dn, attrlist=[attr,])
            except ldap.LDAPError as e:
                err = e
            if isinstance(err, ldap.NO_SUCH_OBJECT) and name in CONFIG_MAP2:
                try:
                    (dn, attr) = CONFIG_MAP2[name]
                    ent = self._instance.getEntry(dn, attrlist=[attr,])
                    err = None
                except ldap.LDAPError as e:
                    err = e
            if isinstance(err, ldap.SERVER_DOWN):
                # Search in config.
                break
            if err is not None:
                raise self._pretty_exception(err, f"while searching attribute {attr} in entry {dn} on server {self.serverid}")
            # If the server doesn't have it, fall back to our configuration.
            if attr is not None:
                v = ensure_str(ent.getValue(attr))
            else:
                v = None
            # Do we need to post-process the value?
            if name == 'version' and v is not None:
                # We need to post process this - it's 389-Directory/1.4.2.2.20191031git8166d8345 B2019.304.19
                # but we need a string like: 1.4.2.2.20191031git8166d8345
                v = v.split('/')[1].split()[0]
            return v
        # Else get from the config
        if self._config:
            if self._serverid is not None:
                return ensure_str(self._config.get(SECTION, name).format(instance_name=self._serverid))
            else:
                return ensure_str(self._config.get(SECTION, name))
        else:
            raise LookupError("""Invalid state
No paths config (defaults.inf) could be found.
This may be because the remote instance is offline, or your /etc/hosts is misconfigured for a local instance
""")

    @property
    def asan_enabled(self):
        if self._defaults_cached is False and self._islocal:
            self._read_defaults()
            self._validate_defaults()
        if self._config and self._config.has_option(SECTION, 'asan_enabled'):
            if self._config.get(SECTION, 'asan_enabled') == '1':
                return True
        return False

    @property
    def with_systemd(self):
        if self._defaults_cached is False and self._islocal:
            self._read_defaults()
            self._validate_defaults()
        if self._is_container:
            # We never have systemd in a container, so check the marker.
            return False
        if self._config and self._config.has_option(SECTION, 'with_systemd'):
            if self._config.get(SECTION, 'with_systemd') == '1':
                return True
        return False

    @property
    def rust_enabled(self):
        if self._defaults_cached is False:
            self._read_defaults()
            self._validate_defaults()
        if self._config and self._config.has_option(SECTION, 'enable_rust'):
            if self._config.get(SECTION, 'enable_rust') == 'no':
                return False
        return True


#-*-encoding:utf-8-*-
import os,sys
from PIL import Image
import subprocess
import cv2
import numpy as np
import threading

py_dir = os.path.dirname(os.path.realpath(__file__))
project_dir = os.path.dirname(py_dir)
sys.path.append(project_dir)
import img_process.utils.resize as resize
import api_invoice.utils.data as data
import img_process.utils.change as change
import img_process.utils.check as check
import api_invoice.service.text as text
import api_common.utils.log as logger
import datetime
import threadpool
import time
import shutil
import uuid
import api_invoice.service.cardno as cardno_service
import api_invoice.service.vinno as vinno_service
import api_invoice.service.organno as organno_service
import api_invoice.service.engineno as engineno_service
import api_invoice.service.price as price_service
import api_invoice.service.img as img_service
import api_invoice.config.profile as profile_config
import api_invoice.dao.invoice_dao as invoice_dao
import api_invoice.dao.log_dao as log_dao
##入口初始化
## 设置profile
profile_config.profile.set_profile(sys.argv[0])

import tensorflow as tf
from keras.backend.tensorflow_backend import set_session
config = tf.ConfigProto()
config.gpu_options.per_process_gpu_memory_fraction = 0.3
set_session(tf.Session(config=config))

#公共参数
py_dir = os.path.dirname(os.path.realpath(__file__))
project_dir = os.path.dirname(py_dir)

img_file= project_dir+"/data/invoice/img.txt"
result_file= project_dir+"/data/invoice/result.txt"

file_dir_img_root = project_dir+"/data/invoice/img/"
file_dir_img_error_root = project_dir+"/data/invoice/img_error/"
file_dir_img_tesseract_root = project_dir+"/data/invoice/img_tesseract/"

if not os.path.exists(file_dir_img_root):
    os.mkdir(file_dir_img_root)

if not os.path.exists(file_dir_img_error_root):
    os.mkdir(file_dir_img_error_root)
else :
    shutil.rmtree(file_dir_img_error_root)
    os.mkdir(file_dir_img_error_root)

if not os.path.exists(file_dir_img_tesseract_root):
    os.mkdir(file_dir_img_tesseract_root)
else :
    shutil.rmtree(file_dir_img_tesseract_root)
    os.mkdir(file_dir_img_tesseract_root)
test_name=[]

#test_name.append("111")
#test_name.append("autohomecar__wKjBwlgmeSaAJrTHAAG-BeYqJoM741")

#test_name.append("41586520-7668-chbe-1gce-n204abm4cf7d")
#test_name.append("04005040-7417-41d5-be2d-n203a829dmge")
#test_name.append("autohomecar__wKjBw1b7NFaAWJkvAAKAyzSQbeo282")
#test_name.append("autohomecar__wKjBw1g9EPOAEIgFAAHQVHt-NE8287")
#test_name.append("autohomecar__wKjBzFghLxiAN0CnADRxl7NnxJE096")
#test_name.append("01362710-8011-h74m-622d-n204afcc45mt")

muilti_thread = False

width =2048
exclude=[]
target_path = project_dir + "/tmp_predict/test3"
if os.path.exists(target_path):
    shutil.rmtree(target_path)
    os.mkdir(target_path)

target_path_error_char = project_dir + "/tmp_predict/error_char"
if os.path.exists(target_path_error_char):
    shutil.rmtree(target_path_error_char)
    os.mkdir(target_path_error_char)

target_path4 = project_dir + "/tmp_predict/test4"
if os.path.exists(target_path4):
    shutil.rmtree(target_path4)
    os.mkdir(target_path4)
else :
    #os.mkdir(target_path4)
    pass

mydateset_base_dir = "/home/autoai/mydataset/original/"

mydateset_base_dir2 = os.path.join(project_dir,"data/invoice/temp")
print("====mydateset_base_dir====",mydateset_base_dir)

def img_process(img):
    begin = datetime.datetime.now()
    id = img["id"]
    path = img["path"]
    file_name = img["name"]
    file_suffix = img["suffix"]
    #file_suffix='jpg'
    if (test_name == None or file_name in test_name or len(test_name) == 0):
        file_path_resize=None

        # 原图
        try:
            file_path_src = file_dir_img_root + file_name + '.' + file_suffix

            pil_img = Image.open(file_path_src)
            if pil_img.size[0]*pil_img.size[1]<480000:
                invoice_dao.update_error_status_by_id("图片分辨率太低,至少大于800*600",id)
                return
            file_path_src_copy = file_dir_img_root + file_name + '/000_src_copy' + file_name + '.' + file_suffix
            # 横竖调整图
            file_path_change_wh = file_dir_img_root + file_name + '/001_change_wh' + file_name + '.' + file_suffix
            # 检测发票表格图
            file_path_rect = file_dir_img_root + file_name + '/002_rect' + file_name + '.' + file_suffix
            # 大小调整
            file_path_resize = file_dir_img_root + file_name + '/003_resize' + file_name + '.' + file_suffix
            # 灰度二值图
            #file_path_gray = file_dir_img_root + file_name + '/gray' + file_name + '.' + file_suffix
            # 上下调整图
            file_path_change_tb = file_dir_img_root + file_name + '/004_change_tb' + file_name + '.' + file_suffix

            file_path_box_dir = file_dir_img_root + file_name + '/box'

            cv2.imwrite(file_path_src_copy, cv2.imread(file_path_src))
            # 横竖处理
            #change.change_wh(file_path_src, file_path_change_wh)

            # 上下重置
            # change.change_tb(file_path_resize,file_path_change_tb)
            # 矫正并抽出中心内容

            check_result = check.check_rect(file_path_src, file_path_rect)
            """
            if check_result:
                area = check_result["all_area"]
                check_result_new =check.check_rect(file_path_rect, file_path_rect+"_new.jpg",level='simple')
                if check_result_new:
                    area_new = check_result_new["area"]
                    if area_new > area*0.55:
                        file_path_rect = file_path_rect+"_new.jpg"
                        print("========= check_reck twice")
                    print("===========area",area,area_new)
            """
            # 大小重置
            resize.resize(file_path_rect, file_path_resize, width)

            change.change_tb(file_path_resize, file_path_change_tb)
        except Exception as e:
            print(e)
        finally:
            pass

        result = {}
        result["info"] = {}
        result["log"] = {}
        result["debug"] = {}
        info = result.get("info")

        try:
            if (file_path_resize):
                img_service.get_text(cardno_service,file_path_resize,file_path_change_tb,file_name,file_path_box_dir,result,file_dir_img_root)
        #except Exception as e:
        #    print(e)
        finally:
            pass

        cardno = info.get("cardno")
        #if cardno:
        #    invoice_dao.update_idcardno_by_id(cardno,id)
        #机构代码识别
        if not cardno:
            try:
                if (file_path_resize):
                    img_service.get_text(organno_service, file_path_resize, file_path_change_tb, file_name, file_path_box_dir,
                                 result,file_dir_img_root)
            except Exception as e:
                print(e)
            #if organno:
                #invoice_dao.update_roganno_by_id(organno, id)
        organno = info.get("organno");
        try:
            if (file_path_resize):
                img_service.get_text(vinno_service, file_path_resize, file_path_change_tb, file_name, file_path_box_dir,result,file_dir_img_root)
        except Exception as e:
            print(e)
        finally:
            pass
        vinno = info.get("vinno");
        #if vinno:
            #invoice_dao.update_vin_by_id(vinno, id)

        try:
            if (file_path_resize):
                img_service.get_text(engineno_service, file_path_resize, file_path_change_tb, file_name, file_path_box_dir, result,
                     file_dir_img_root)
        except Exception as e:
            print(e)
        engineno = info.get("engineno");
        if engineno:
            #invoice_dao.update_engineno_by_id(engineno, id)
            build_check_char_img("engineno", info, result)

        try:
            if (file_path_resize):
                img_service.get_text(price_service, file_path_resize, file_path_change_tb, file_name, file_path_box_dir, result,
                     file_dir_img_root)
        except Exception as e:
            print(e)

        price = info.get("price");
        if price:
            #invoice_dao.update_price_by_id(price, id)
            build_check_char_img("price", info, result)
        if not cardno:
            invoice_dao.update_unknow_status_by_id(id)
        end = datetime.datetime.now()
        #predict_time =(end - begin).microseconds//1000
        predict_time =(end - begin).seconds
        predict_type_idcard = result["debug"].get("predict_type_cardno")
        invoice_dao.update_invoice_by_id(id,idcard=cardno,vin=vinno,organ=organno,engine=engineno,price=price,predict_time=predict_time,predict_type_idcard=predict_type_idcard)

        out_result = {}
        out_result["time"] = predict_time
        invoice_dao.update_predict_time_by_id(out_result["time"], id)
        out_result["file_name"] = file_name
        out_result["info"] = result["info"]
        #out_result["cardno_machine_default"] = cardno_machine_default
        out_result["log"] = result["log"]

        out_result["page_top"] = result["debug"].get("page_top")
        log_dao.info(str(out_result),"invoice",img["id"])
        with open(result_file, 'a') as f:
            f.write(str(out_result)+"\n")
        thread = threading.current_thread()
        t=thread_list.get(thread.name)
        if t!=None:
            thread_list.pop(thread.name)

def build_check_char_img(field_name,info,result,server_char_dir="upper_201706",server_number_dir="number_201706",server_signal_dir="signal_201706",char_set="ABCDEFGHIJKLMNOPQRSTUVWXYZ",num_set="0123456789",signal_set=".¥-"):
    target_mydateset_base_dir=mydateset_base_dir
    if not os.path.exists(target_mydateset_base_dir):
        target_mydateset_base_dir =mydateset_base_dir2
    server_char_path = os.path.join(target_mydateset_base_dir,server_char_dir)
    if not os.path.exists(server_char_path):
        os.makedirs(server_char_path)
    server_number_path = os.path.join(target_mydateset_base_dir,server_number_dir)
    if not os.path.exists(server_number_path):
        os.makedirs(server_number_path)
    server_signal_path = os.path.join(target_mydateset_base_dir,server_signal_dir)
    if not os.path.exists(server_signal_path):
        os.makedirs(server_signal_path)
    field = info.get(field_name);
    field_file = result.get(field_name+"_file")
    logger.info("=============="+field_name+","+field_name+"_file", field, field_file)
    if field_file and field:
        text_type = result["log"][field_name+"_type"]
        if text_type.startswith("tesseract"):
            target_dir = file_dir_img_tesseract_root + file_name + "_"+field_name
            if os.path.exists(target_dir):
                shutil.rmtree(target_dir)
                # os.mkdir(target_dir)
            else:
                pass
                # os.mkdir(target_dir)
            shutil.copytree(file_dir_img_root + file_name, target_dir)
        img_src_name = os.path.basename(os.path.dirname(os.path.dirname(os.path.dirname(field_file))))
        box_dir = field_file + "_dir"
        box_src_dir = field_file + "_dir_src"
        logger.debug("=============="+field+",box_dir", field, box_dir)
        if os.path.exists(box_dir):
            files = os.listdir(box_dir)
            files_len = len(files)
            logger.info("=============", files_len, len(field), field, files)
            if files_len == len(field):
                logger.info("============= build box img :" + field)
                value = field
                for i in range(0, len(field)):
                    char_text = field[i]
                    try:
                        if char_text in num_set:
                            if os.path.exists(server_number_path):
                                shutil.copyfile(box_src_dir + "/" + str(i).zfill(3) + ".jpg",
                                                server_number_path + "/" + char_text + "_" + str(i).zfill(
                                                    3) + "_" + value + "_" + img_src_name + ".jpg")
                            pass
                        if char_text in char_set:
                            if os.path.exists(server_char_path):
                                shutil.copyfile(box_dir + "/" + str(i).zfill(3) + ".jpg",
                                                server_char_path + "/" + char_text + "_" + str(i).zfill(
                                                    3) + "_" + value + "_" + img_src_name + ".jpg")
                        if char_text in signal_set:
                            if os.path.exists(server_signal_path):
                                shutil.copyfile(box_dir + "/" + str(i).zfill(3) + ".jpg",
                                                server_signal_path + "/" + char_text + "_" + str(i).zfill(
                                                    3) + "_" + value + "_" + img_src_name + ".jpg")
                                pass
                    # except Exception as e:
                    #    logger.error("======:Exception:",e)
                    #    pass
                    finally:
                        pass
            else:
                logger.warn("================file and dada is diff================")
    else:
        target_dir = file_dir_img_error_root + file_name + "_"+field
        if os.path.exists(target_dir):
            shutil.rmtree(target_dir)
            # os.mkdir(target_dir)
        else:
            pass
            # os.mkdir(target_dir)
        shutil.copytree(file_dir_img_root + file_name, target_dir)
        pass
        # engineno

if os.path.exists(result_file):
    os.remove(result_file)
global thread_list
thread_list ={}

index = 0

def get_target_imgs():
    if len(test_name) == 0:
        # 读取图片列表
        imgs = data.getimgs(img_file, file_dir_img_root)
    else:
        muilti_thread = False
        if os.path.exists(file_dir_img_root):
            shutil.rmtree(file_dir_img_root)
            os.mkdir(file_dir_img_root)
        imgs = data.get_by_filenames(test_name, file_dir_img_root)
    target_imgs = []
    if imgs:
        for img in imgs:
            file_name = img["name"]
            # print(file_name)
            if file_name in exclude:
                # break
                pass
            else:
                file_path_src_dir = file_dir_img_root + file_name
                # print(file_path_src_dir)
                if os.path.exists(file_path_src_dir):
                    shutil.rmtree(file_path_src_dir)

                file_suffix = img["suffix"]
                if not test_name or len(test_name) == 0:
                    target_imgs.append(img)
                elif file_name in test_name:
                    target_imgs.append(img)
    return target_imgs

target_imgs = get_target_imgs()

if muilti_thread:
    pool = threadpool.ThreadPool(40)
    requests = threadpool.makeRequests(img_process, target_imgs)
    [pool.putRequest(req) for req in requests]
    pool.wait()
else :
    while target_imgs and len(target_imgs)>0:
        imgs_len = len(target_imgs)
        for img in target_imgs:
            index += 1
            path = img["path"]
            file_name = img["name"]
            print("=======begin=====================", index, "/", imgs_len,"[",img["id"],"]", file_name)
            img_process(img)
            print("=======end=====================", index, "/", imgs_len,"[",img["id"],"]")
        if len(test_name) == 0:
            target_imgs = get_target_imgs()
        else :
            break
text.write_param_config()


from webargs import fields, validate
from .. import constants

filter_args = {
    "resolution": fields.Str(
        missing="1D", validate=lambda r: r in constants.INTERVALS
    ),
    "after": fields.Int(
        missing=None, validate=lambda v: v > 0
    )
}

transactions_args = filter_args
transactions_args["currency"] = fields.Str(
    missing="AOK"
)


from pnmlpy import WorkflowVerifier

class TestControlFlow:

    def test_file(self):
        errors = WorkflowVerifier.run_verifier('testResources/runningexample.pnml')
        import json
        js = json.loads(json.dumps(errors, sort_keys=False, indent=4))
        assert True == js["soundness"]
        assert 3 == int(js["cycles"])


""" Tests for `typing_json.typechecking.to_json_obj` """
# pylint: disable = line-too-long, invalid-name, missing-docstring

# standard imports
import json
import typing
from typing import Union, Optional, List, Tuple, Set, FrozenSet, Mapping, Dict, NamedTuple, Deque
from decimal import Decimal
from collections import deque, OrderedDict

# external dependencies
from typing_extensions import Literal, TypedDict

# internal imports
from typing_json.typechecking import TYPECHECKABLE_BASE_TYPES
from typing_json.encoding import to_json_obj, JSON_BASE_TYPES
from typing_json.decoding import from_json_obj, JSON_BASE_TYPES

# (bool, int, float, str, type(None))
NONENCODABLE_BASE_TYPES = tuple(t for t in TYPECHECKABLE_BASE_TYPES if t not in JSON_BASE_TYPES+(Decimal,))

def failure_callback(message: str) -> None:
    print(message)

def test_from_json_obj_typeerrors():
    """ Checks that `from_json_obj` raises `TypeError` on non-typecheckable types or non-json-encodable types.
    """
    class NonTypechekableT:
        name: str
        val: int
        def __init__(self, name, val):
            self.name = name
            self.val = val
    x = NonTypechekableT("x", 0)
    try:
        from_json_obj(x, NonTypechekableT)
        assert False
    except TypeError:
        assert True

BASETYPES_ENCODINGS = [
    (True, bool, True),
    (1, int, 1),
    (1.5, float, 1.5),
    ("hello", str, "hello"),
    (None, type(None), None),
    (None, None, None),
    (Decimal("1.0"), Decimal, 1),
    (Decimal("1.5"), Decimal, "1.5"),
    (True, Literal[True, 1.5, None], True),
    (1.5, Literal[True, 1.5, None], 1.5),
    (None, Literal[True, 1.5, None], None),
    (True, Union[bool, float, Decimal], True),
    (1.5, Union[bool, float, Decimal], 1.5),
    (Decimal("1.0"), Union[bool, None, Decimal], 1),
    (Decimal("1.5"), Union[bool, None, Decimal], "1.5"),
    (1, int, Decimal(1)),
    (1, int, Decimal("1.0")),
]

def test_from_json_obj_basetypes():
    """ Test `to_json_obj` on JSON base types and `decimal.Decimal`. """
    for val, t, encoding in BASETYPES_ENCODINGS:
        assert from_json_obj(encoding, t) == val

def test_from_json_obj_numbers():
    assert from_json_obj(1.5, Decimal) == Decimal(1.5)
    assert from_json_obj(1, float) == 1.0
    assert from_json_obj(Decimal("1.5"), float) == 1.5
    assert from_json_obj(Decimal("1.0"), float) == 1.0
    try:
        from_json_obj(Decimal("1.5"), float, cast_decimal=False)
        assert False
    except TypeError:
        assert True

from enum import Enum
class EnumT(Enum):
    # pylint:disable=all
    Red = 0
    Green = 1
    Blue = 2

def test_from_json_obj_enums():
    assert from_json_obj("Red", EnumT) == EnumT.Red

def test_from_json_obj_lists():
    """ Checks that lists are decoded correctly. """
    encoding = [1, 2, 3]
    val = from_json_obj(encoding, List[int])
    assert isinstance(val, list)
    assert len(val) == 3
    assert all(val[i] == encoding[i] for i in range(len(encoding)))

def test_from_json_obj_tuples1():
    """ Checks that fixed-length tuples are decoded correctly. """
    encoding = [1, 2, 3]
    val = from_json_obj(encoding, Tuple[int, int, int])
    assert isinstance(val, tuple)
    assert len(val) == 3
    assert all(val[i] == encoding[i] for i in range(len(encoding)))

def test_from_json_obj_tuples2():
    """ Checks that variadic tuples are decoded correctly. """
    encoding = [1, 2, 3]
    val = from_json_obj(encoding, Tuple[int, ...])
    assert isinstance(val, tuple)
    assert len(val) == 3
    assert all(val[i] == encoding[i] for i in range(len(encoding)))

def test_from_json_obj_deque():
    """ Checks that dequeues are decoded correctly. """
    encoding = [1, 2, 3]
    val = from_json_obj(encoding, Deque[int])
    assert isinstance(val, deque)
    assert len(val) == 3
    assert all(val[i] == encoding[i] for i in range(len(encoding)))

def test_from_json_obj_set():
    """ Checks that dequeues are decoded correctly. """
    encoding = [1, 2, 3]
    val = from_json_obj(encoding, Set[int])
    assert isinstance(val, set)
    assert set(val) == set(encoding)

def test_from_json_obj_frozenset():
    """ Checks that dequeues are decoded correctly. """
    encoding = [1, 2, 3]
    val = from_json_obj(encoding, FrozenSet[int])
    assert isinstance(val, frozenset)
    assert set(val) == set(encoding)

DICT_ENCODINGS = [
    ({str(i): i for i in range(3)}, Dict[str, int], {str(i): i for i in range(3)}),
    ({str(i): i for i in range(3)}, Mapping[str, int], {str(i): i for i in range(3)}),
    ({str(i): i for i in range(3)}, Dict[Literal["0", "1", "2"], int], {str(i): i for i in range(3)}),
    ({str(i): i for i in range(3)}, Mapping[Literal["0", "1", "2"], int], {str(i): i for i in range(3)}),
    ({EnumT.Red: 0, EnumT.Green: 1, EnumT.Blue: 2}, Dict[EnumT, int], {"Red": 0, "Green": 1, "Blue": 2}),
    ({EnumT.Red: 0, EnumT.Green: 1, EnumT.Blue: 2}, Mapping[EnumT, int], {"Red": 0, "Green": 1, "Blue": 2}),
    ({tuple(j for j in range(i)): i for i in range(3)}, Dict[Tuple[int, ...], int], {json.dumps([j for j in range(i)]): i for i in range(3)}),
    ({tuple(j for j in range(i)): i for i in range(3)}, Mapping[Tuple[int, ...], int], {json.dumps([j for j in range(i)]): i for i in range(3)}),
]

def test_from_json_obj_dicts():
    """ Checks that dicts are decoded into dicts with the correct key/value pairs. """
    def _assert_eq_dicts(d1, d2):
        assert isinstance(d1, dict)
        assert isinstance(d2, dict)
        assert len(d1) == len(d2)
        assert set(d1.keys()) == set(d2.keys())
        assert all(d1[key] == d2[key] for key in d1)
    for val, t, encoding in DICT_ENCODINGS:
        _assert_eq_dicts(from_json_obj(encoding, t), val)

ORDERED_DICT_ENCODINGS = [
    (OrderedDict([(str(i), i) for i in range(3)]), typing.OrderedDict[str, int], OrderedDict([(str(i), i) for i in range(3)])),
    (OrderedDict([(str(i), i) for i in range(3)]), typing.OrderedDict[Literal["0", "1", "2"], int], OrderedDict([(str(i), i) for i in range(3)])),
    (OrderedDict([(EnumT.Red, 0), (EnumT.Green, 1), (EnumT.Blue, 2)]), typing.OrderedDict[EnumT, int], OrderedDict([("Red", 0), ("Green", 1), ("Blue", 2)])),
    (OrderedDict([(tuple(j for j in range(i)), i) for i in range(3)]), typing.OrderedDict[Tuple[int, ...], int], OrderedDict([(json.dumps([j for j in range(i)]), i) for i in range(3)])),
]

def test_from_json_obj_ordereddicts():
    """ Checks that dicts are decoded into dicts with the correct key/value pairs. """
    def _assert_eq_ordered_dicts(d1, d2):
        assert isinstance(d1, OrderedDict)
        assert isinstance(d2, OrderedDict)
        assert len(d1) == len(d2)
        assert tuple(d1.keys()) == tuple(d2.keys())
        assert all(d1[key] == d2[key] for key in d1)
    for val, t, encoding in ORDERED_DICT_ENCODINGS:
        _assert_eq_ordered_dicts(from_json_obj(encoding, t), val)

class NamedTupleExampleT(NamedTuple):
    name: str
    value: Union[int, float]
    flag: bool = False

class NamedTupleNastyExampleT(NamedTuple):
    name: str
    value: Dict[str, float]
    flag: bool = False

def test_is_json_encodable_namedtuple():
    """
        Tests the encoding of namedtuples.
    """
    t = NamedTupleExampleT("t", 1)
    t_encoding = OrderedDict([("name", "t"), ("value", 1)])
    assert from_json_obj(t_encoding, NamedTupleExampleT) == t
    nt = NamedTupleNastyExampleT("t", {"x": 1.0, "y": 0.0})
    nt_encoding_list = ["t", {"x": Decimal("1.0"), "y": 0}]
    assert from_json_obj(nt_encoding_list, NamedTupleNastyExampleT) == nt
    nt_encoding_list_long = ["t", {"x": Decimal("1.0"), "y": 0}, False]
    assert from_json_obj(nt_encoding_list_long, NamedTupleNastyExampleT) == nt
    try:
        nt_encoding_list_too_long = ["t", {"x": Decimal("1.0"), "y": 0}, False, 1]
        from_json_obj(nt_encoding_list_too_long, NamedTupleNastyExampleT) == nt
    except TypeError:
        assert True

WRONG_TYPE_ENCODINGS = [
    (bool, 1),
    (int, True),
    (float, "hello"),
    (str, 1.5),
    (type(None), 1),
    (None, 1),
    (Decimal, "hi"),
    (EnumT, 1.2),
    (EnumT, "Yellow"),
    (List[int], "hello"),
    (Tuple[int, ...], tuple([1, 2, 3])),
    (Tuple[int, int, int], tuple([1, 2, 3])),
    (Tuple[int, int, int], [1, 2]),
    (Deque[int], deque([1, 2, 3])),
    (Set[int], set([1, 2, 3])),
    (FrozenSet[int], frozenset([1, 2, 3])),
    (Literal[1,2,3], "1.0"),
    (Union[int, float], False),
    (Dict[str, int], [1, 2, 3]),
    (Mapping[str, int], [1, 2, 3]),
    (typing.OrderedDict[str, int], [1, 2, 3]),
    (Dict[str, int], {1: 1, 2: 2, 3: 3}),
    (Mapping[str, int], {1: 1, 2: 2, 3: 3}),
    (typing.OrderedDict[str, int], OrderedDict({1: 1, 2: 2, 3: 3})),
    (NamedTupleExampleT, ("t", 1)),
    (NamedTupleExampleT, OrderedDict([("name", "t"), ("values", [1, 2, 3])])),
    (NamedTupleExampleT, OrderedDict([("name", "t"), ("value", 1), ("blah", None)])),
    (NamedTupleExampleT, OrderedDict([("name", "t")])),
]

def test_from_json_obj_wrong_type():
    """ Test `to_json_obj` on wrong encodings for JSON base types and `decimal.Decimal`. """
    for t, encoding in WRONG_TYPE_ENCODINGS:
        try:
            from_json_obj(encoding, t)
            assert False, "Should not be decoding %s as %s."%(str(encoding), str(t))
        except TypeError:
            assert True

def test_from_json_obj_large_collections_namedtuple():
    class Pair(NamedTuple):
        left: int
        right: int
    large_list: List[Pair] = []
    for i in range(1000):
        large_list.append(Pair(i, i+1))
    assert from_json_obj(to_json_obj(large_list, List[Pair], namedtuples_as_lists=False), List[Pair]) == large_list
    assert from_json_obj(to_json_obj(large_list, List[Pair], namedtuples_as_lists=True), List[Pair]) == large_list

def test_from_json_typed_dict():
    class Pair(TypedDict, total=True):
        left: int
        right: int
    assert from_json_obj({"left": 0, "right": 1}, Pair) == {"left": 0, "right": 1}
    try:
        from_json_obj("not a dict", Pair)
        assert False, "Should not be decoding string as TypedDict."
    except TypeError:
        assert True
    try:
        from_json_obj({"left": 0}, Pair)
        assert False, "Should not be decoding dict with missing key as TypedDict (total=True)."
    except TypeError:
        assert True
    try:
        from_json_obj({"left": 0, "right": 1, "center": 2}, Pair)
        assert False, "Should not be decoding dict with extra key as TypedDict (total=True)."
    except TypeError:
        assert True
    class PartialPair(TypedDict, total=False):
        left: int
        right: int
    try:
        from_json_obj({"left": 0}, PartialPair)
        assert True, "Should be decoding dict with missing key as TypedDict (total=False)."
    except TypeError:
        assert False


#!/usr/bin/env python
# coding: utf-8

# In[1]:

import pygame
from pygame.locals import *

pygame.init()

# In[2]:

#Screen Dimensions
screen_width = 600
screen_height = 600

screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('Breakout')

#Define Font
font = pygame.font.SysFont('Constantia', 30)

#define colors
background = (234, 218, 184)

#Blocks
brick_red = (242, 85, 96)
brick_green = (86, 174, 87)
brick_blue = (69, 177, 232)

#Paddle Colors
paddle_col = (142, 135, 123)
paddle_outline = (100, 100, 100)

text_color = (78, 81, 139)

#Define game variables
cols = 6
rows = 6
clock = pygame.time.Clock()
fps = 60
live_ball = False
game_over = 0

# In[3]:

#Print Text

def draw_text(text, font, text_color, x, y):
    img = font.render(text, True, text_color)
    screen.blit(img, (x, y))

# In[4]:

#Brick Class

class Brick():

    def __init__(self):
        self.width = screen_width // cols
        self.height = 50

    def create_brick(self):
        self.bricks = []

        #Create emply list
        brick_individual = []
        for row in range(rows):
            brick_row = []

            for col in range(cols):
                brick_x = col * self.width
                brick_y = row * self.height
                rect = pygame.Rect(brick_x, brick_y, self.width, self.height)

                if row < 2:
                    strength = 3
                elif row < 4:
                    strength = 2
                elif row < 6:
                    strength = 1

                brick_individual = [rect, strength]
                brick_row.append(brick_individual)

            self.bricks.append(brick_row)

    def draw_wall(self):

        for row in self.bricks:

            for brick in row:
                if brick[1] == 3:
                    brick_color = brick_blue
                elif brick[1] == 2:
                    brick_color = brick_green
                elif brick[1] == 1:
                    brick_color = brick_red

                pygame.draw.rect(screen, brick_color, brick[0])
                pygame.draw.rect(screen, background, (brick[0]), 2)

# In[5]:

#Paddle Class

class Paddle():
    def __init__(self):
        self.reset()

    def move(self):
        self.direction = 0

        key = pygame.key.get_pressed()
        if key[pygame.K_LEFT] and self.rect.left > 0:
            self.rect.x -= self.speed
            self.direction = -1

        if key[pygame.K_RIGHT] and self.rect.right < screen_width:
            self.rect.x += self.speed
            self.direction = 1

    def draw(self):
        pygame.draw.rect(screen, paddle_col, self.rect)
        pygame.draw.rect(screen, paddle_outline, self.rect, 3)

    def reset(self):
        self.height = 20
        self.width = int(screen_width / cols)
        self.x = int((screen_width / 2) - (self.width / 2))
        self.y = screen_height - (self.height * 2)
        self.speed = 10
        self.rect = Rect(self.x, self.y, self.width, self.height)
        self.direction = 0

# In[6]:

#Ball Class

class game_ball():
    def __init__(self, x, y):
        self.reset(x, y)

    def draw(self):
        pygame.draw.circle(screen, paddle_col,
                           (self.rect.x + self.ball_radius,
                            self.rect.y + self.ball_radius),
                            self.ball_radius)
        pygame.draw.circle(screen, paddle_outline,
                           (self.rect.x + self.ball_radius,
                            self.rect.y + self.ball_radius),
                            self.ball_radius, 3)

    def move(self):

        collision_threshold = 5

        wall_destroyed = 1

        row_count = 0
        for row in wall.bricks:

            item_count = 0
            for item in row:
                if self.rect.colliderect(item[0]):
                    if abs(self.rect.bottom - item[0].top) < collision_threshold and self.speed_y > 0:
                        self.speed_y *= -1
                    if abs(self.rect.top - item[0].bottom) < collision_threshold and self.speed_y < 0:
                        self.speed_y *= -1
                    if abs(self.rect.right- item[0].left) < collision_threshold and self.speed_x > 0:
                        self.speed_x *= -1
                    if abs(self.rect.left - item[0].right) < collision_threshold and self.speed_x < 0:
                        self.speed_x *= -1

                    if wall.bricks[row_count][item_count][1] > 1:
                        wall.bricks[row_count][item_count][1] -= 1
                    else:
                        wall.bricks[row_count][item_count][0] = (0, 0, 0, 0)

                if wall.bricks[row_count][item_count][0] != (0, 0, 0, 0):
                    wall_destroyed = 0

                item_count += 1
            row_count += 1

        if wall_destroyed == 1:
            self.game_over = 1

        if self.rect.left < 0 or self.rect.right > screen_width:
            self.speed_x *= -1

        if self.rect.top < 0:
            self.speed_y *= -1
        if self.rect.bottom > screen_height:
            self.game_over = -1

        if self.rect.colliderect(player_paddle):
            if abs(self.rect.bottom - player_paddle.rect.top) < collision_threshold and self.speed_y > 0:
                self.speed_y *= -1
                self.speed_x += player_paddle.direction
                if self.speed_x > self.speed_max:
                    self.speed_x = self.speed_max
                elif self.speed_x < 0 and self.speed_x < -self.speed_max:
                    self.speed_x = -self.speed_max
            else:
                self.speed_x *= -1

        self.rect.x += self.speed_x
        self.rect.y += self.speed_y

        return self.game_over

    def reset(self, x, y):
        self.ball_radius = 10
        self.x = x - self.ball_radius
        self.y = y
        self.rect = Rect(self.x, self.y, self.ball_radius*2, self.ball_radius*2)
        self.speed_x = 4
        self.speed_y = -4
        self.speed_max = 5
        self.game_over = 0

# In[7]:

#Create Wall
wall = Brick()
wall.create_brick()

#Create Paddle
player_paddle = Paddle()

#Create Ball
ball = game_ball(player_paddle.x + (player_paddle.width // 2),
                 player_paddle.y - player_paddle.height)

# In[8]:

run = True

while run:

    clock.tick(fps)

    screen.fill(background)

    wall.draw_wall()
    player_paddle.draw()
    ball.draw()

    if live_ball:
        player_paddle.move()
        game_over = ball.move()
        if game_over != 0:
            live_ball = False

    if not live_ball:
        if game_over == 0:
            draw_text('CLICK ANYWHERE TO START', font, text_color, 100, screen_height // 2 + 100)
        if game_over == 1:
            draw_text('YOU WON!', font, text_color, 240, screen_height // 2 + 50)
            draw_text('CLICK ANYWHERE TO START', font, text_color, 100, screen_height // 2 + 100)
        if game_over == -1:
            draw_text('YOU LOST!', font, text_color, 240, screen_height // 2 + 50)
            draw_text('CLICK ANYWHERE TO START', font, text_color, 100, screen_height // 2 + 100)

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        if event.type == pygame.MOUSEBUTTONDOWN and live_ball == False:
            live_ball = True
            ball.reset(player_paddle.x + (player_paddle.width // 2),
                       player_paddle.y - player_paddle.height)
            player_paddle.reset()
            wall.create_brick()

    pygame.display.update()

pygame.quit()


import json
from utils.db_utils import RabbitConn, init_db, init_rabbit
from services import logger_service, classifier_service, eval_service, experiment_service, model_service, orthanc_service, study_service
from services import messaging_service
import json
import traceback

def on_classifier_result(ch, method, properties, body):
    print(f'received classifier result {body}')
    message = json.loads(body)
    orthanc_id = message['id']
    result = message['output']
    classifier_service.save_classification(orthanc_id, result)

    messaging_service.send_notification(f'Study {orthanc_id} ready', 'new_result', -1)

def on_eval_result(ch, method, properties, body):
    try:
        print(f'received eval result {body}')
        message = json.loads(body)
        eval_id = message['id']
        result = message['output']
        msg_type = message['type']
        print('recieved result: ', result)
        if msg_type == 'START':
            messaging_service.send_notification(f'Finished evaluation {eval_id}', 'new_result', -1)

            eval_service.set_eval_as_running(eval_id)
            return
        if msg_type == 'FAIL' or type(result) is not dict:
            eval_service.fail_dicom_eval(eval_id)
            return
        # write result to db
        e = eval_service.write_eval_results(result, eval_id)

        study = study_service.get_study_by_eval_id(eval_id)
        # orthanc_service.delete_study_dicom(study['orthancStudyId'])
        # send notification to frontend
        messaging_service.send_notification(f'Finished evaluation {eval_id}', 'new_result', -1)
    except:
        eval_service.fail_dicom_eval(eval_id)
        print('failed to get result', body)
        traceback.print_stack()

def on_eval_log(ch, method, properties, body):
    try:
        print(f'received eval log {body}')
        message = json.loads(body)
        eval_id = message['id']
        result = message['output'].split('\n')
        type = message['type']
        print(result)
        eval_service.add_stdout_to_eval([eval_id], result)
    except:
        print('failed to log', body)
        # traceback.print_stack()

if __name__  == "__main__":
    print('starting results watcher')
    init_rabbit()
    init_db()
    with RabbitConn() as channel:
        channel.queue_declare(messaging_service.EVAL_QUEUE)
        channel.queue_declare(messaging_service.CLASSIFIER_QUEUE)
        channel.queue_declare(messaging_service.LOG_QUEUE)

        channel.basic_consume(queue=messaging_service.CLASSIFIER_QUEUE,
                            on_message_callback=on_classifier_result,
                            auto_ack=True)
        channel.basic_consume(queue=messaging_service.EVAL_QUEUE,
                            on_message_callback=on_eval_result,
                            auto_ack=True)
        channel.basic_consume(queue=messaging_service.LOG_QUEUE,
                            on_message_callback=on_eval_log,
                            auto_ack=True)
        channel.start_consuming()


import collections
import types

'''
Dictionaries in Python: Summary
All the Python dictionary implementations listed in this tutorial are valid implementations that are built into the Python standard library.

If you’re looking for a general recommendation on which mapping type to use in your programs, I’d point you to the built-in dict data type. It’s a versatile and optimized hash table implementation that’s built directly into the core language.

I would recommend that you use one of the other data types listed here only if you have special requirements that go beyond what’s provided by dict.

All the implementations are valid options, but your code will be clearer and easier to maintain if it relies on standard Python dictionaries most of the time.
'''

# called maps, hashmaps, lookup tables, or associative arrays
# 1) Example
phonebook = {
    "bob": 7387,
    "alice": 3719,
    "jack": 7052,
}

squares = {x: x * x for x in range(6)}

print(phonebook["alice"])
print(squares)

'''
- Python’s dictionaries are indexed by keys that can be of any hashable type. A hashable object has a hash value that
never changes during its lifetime (see __hash__), and it can be compared to other objects (see __eq__).
Hashable objects that compare as equal must have the same hash value.
- Immutable types like strings and numbers are hashable and work well as dictionary keys. You can also use tuple
objects as dictionary keys as long as they contain only hashable types themselves.
- Class attributes and variables in a stack frame are both stored internally in dictionaries.
- hash table implementation that provides the performance characteristics you’d expect: O(1) time complexity for lookup, insert, update, and delete operations in the average case.
- third-party dictionary implementations exist, such as skip lists or B-tree–based dictionaries.
'''

# 2) collections.OrderedDict: Remember the Insertion Order of Keys
# if key order is important for your algorithm to work, then it’s best to communicate this clearly by explicitly using the OrderedDict class:
d_or = collections.OrderedDict(one=1, two=2, three=3)
d_simple = dict(one=1, two=2, three=3)
d_or["four"] = 4
d_simple["four"] = 4
print(d_or.keys())
print(d_simple.keys())

# Until Python 3.8, you couldn’t iterate over dictionary items in reverse order using reversed()
# Python reversed() with Built-In Sequence Objects
assert list(reversed(d_or)) == list(reversed(d_simple)) == ['four', 'three', 'two', 'one']
seq_tuple = ('P', 'y', 't', 'h', 'o', 'n')
# reverse of a tuple object
print(list(reversed(seq_tuple)))

# reversed() with Custom Objects
class Vowels:
    vowels = ['v', 'o', 'l', 'v', 'o']

    def __reversed__(self):
        return reversed(self.vowels)
v = Vowels()
# reverse a custom object v
print(list(reversed(v)))

# Reordering Items With .move_to_end()
#  This method allows you to move existing items to either the end or the beginning of the underlying dictionary, so it’s a great tool for reordering a dictionary.
d_or.move_to_end(key='one', last=True) #  True -> to the end, False -> to the beginning
# key holds the key that identifies the item you want to move. If key doesn’t exist, then you get a KeyError.

# 3) collections.defaultdict: Return Default Values for Missing Keys
# The defaultdict class is another dictionary subclass that accepts a callable in its constructor whose return value will be used if a requested key cannot be found.
dd = collections.defaultdict(list)

# Accessing a missing key creates it and
# initializes it using the default factory,
# i.e. list() in this example:
dd["dogs"].append("Rufus")
dd["dogs"].append("Kathrin")
dd["dogs"].append("Mr Sniffles")

print(dd["dogs"])

# 4) collections.ChainMap: Search Multiple Dictionaries as a Single Mapping
dict1 = {"one": 1, "two": 2}
dict2 = {"three": 3, "four": 4}
chain = collections.ChainMap(dict1, dict2)
# ChainMap searches each collection in the chain
# from left to right until it finds the key (or fails):
print(chain["three"])
print(chain["one"])
# print(chain["missing"]) -> err

# collections

# 5) types.MappingProxyType: A Wrapper for Making Read-Only Dictionaries
# frozenset()
# frozendict()
# # Curiously, although we have the seldom useful frozenset, there's still no frozen mapping. The idea was rejected in PEP 416 -- Add a frozendict builtin type. This idea may be revisited in a later Python release, see PEP 603 -- Adding a frozenmap type to collections.
default_config = {'a': 1}
DEFAULTS = types.MappingProxyType(default_config)
# So changes in the default_config will update DEFAULTS as expected, but you can't write to the mapping proxy object
# itself.
default_config["b"] = 2
# DEFAULTS['b'] = 22 # TypeError: 'mappingproxy' object does not support item assignment

def foo(config=DEFAULTS):
    return dict(config)

# Now the default config can be updated dynamically, but remain immutable where you want it to be immutable by
# passing around the proxy instead.

# Admittedly it's not really the same thing as an "immutable, hashable dict", but it might be a decent substitute for
# some use cases of a frozendict.
f = foo()

'''
- MappingProxyType is a wrapper around a standard dictionary that provides a read-only view into the wrapped
dictionary’s data. This class was added in Python 3.3 and can be used to create immutable proxy versions of dictionaries.
- MappingProxyType can be helpful if, for example, you’d like to return a dictionary carrying internal state from a class or module while discouraging write access to this object
- Using MappingProxyType allows you to put these restrictions in place without first having to create a full copy of the dictionary
'''
writable = {"one": 1, "two": 2}
read_only = types.MappingProxyType(writable)
# The proxy is read-only:
print(read_only["one"])
# read_only["one"] = 23 -> error
# Updates to the original are reflected in the proxy:
writable["one"] = 42
print(read_only)

# Alternative
# https://github.com/Marco-Sulla/python-frozendict
from frozendict import frozendict

fd = frozendict({"Guzzanti": "Corrado", "Hicks": "Bill"})
print(fd["Guzzanti"])
# Corrado
# fd["Brignano"] -> KeyError: 'Brignano'
assert len(fd) == 2
assert "Guzzanti" in fd
# True
# assert "Guzzanti" not in fd
# # False
# assert "Brignano" in fd
# # Falses
print(hash(fd))  #e.g. 5833699487320513741

fd_unhashable = frozendict({1: []})
# hash(fd_unhashable)
# TypeError: unhashable type: 'list'
fd | {1: 2}
# frozendict({'Guzzanti': 'Corrado', 'Hicks': 'Bill', 1: 2})

fd5 = frozendict(fd)
id_fd5 = id(fd5)
fd5 |= {1: 2}
fd5
# frozendict.frozendict({'Guzzanti': 'Corrado', 'Hicks': 'Bill', 1: 2})
id(fd5) != id_fd5
# True

fd.set(1, 2)
# frozendict.frozendict({'Guzzanti': 'Corrado', 'Hicks': 'Bill', 1: 2})

fd.set("Guzzanti", "Sabina")
# frozendict.frozendict({'Guzzanti': 'Sabina', 'Hicks': 'Bill'})

fd.delete("Guzzanti")
# frozendict.frozendict({'Hicks': 'Bill'})

fd.setdefault("Guzzanti", "Sabina")
# frozendict.frozendict({'Guzzanti': 'Corrado', 'Hicks': 'Bill'})

fd.setdefault(1, 2)
# frozendict.frozendict({'Guzzanti': 'Corrado', 'Hicks': 'Bill', 1: 2})

fd.key()
# 'Guzzanti'

fd.value(1)
# 'Bill'

fd.item(-1)
# (1, 2)
fd2 = fd.copy()
fd2 == fd
# True

fd3 = frozendict(fd)
fd3 == fd
# True

fd4 = frozendict({"Hicks": "Bill", "Guzzanti": "Corrado"})

print(fd4)
# frozendict({'Hicks': 'Bill', 'Guzzanti': 'Corrado'})

fd4 == fd
# True

import pickle
fd_unpickled = pickle.loads(pickle.dumps(fd))
print(fd_unpickled)
# frozendict({'Guzzanti': 'Corrado', 'Hicks': 'Bill'})
fd_unpickled == fd
# True

frozendict(Guzzanti="Corrado", Hicks="Bill")
# frozendict({'Guzzanti': 'Corrado', 'Hicks': 'Bill'}

frozendict((("Guzzanti", "Corrado"), ("Hicks", "Bill")))
# frozendict({'Guzzanti': 'Corrado', 'Hicks': 'Bill'})

fd.get("Guzzanti")
# 'Corrado'

print(fd.get("Brignano"))
# None

tuple(fd.keys())
# ('Guzzanti', 'Hicks')

tuple(fd.values())
# ('Corrado', 'Bill')

tuple(fd.items())
# (('Guzzanti', 'Corrado'), ('Hicks', 'Bill'))

frozendict.fromkeys(["Corrado", "Sabina"], "Guzzanti")
# frozendict({'Corrado': 'Guzzanti', 'Sabina': 'Guzzanti'})

iter(fd)
# <dict_keyiterator object at 0x7feb75c49188>

# fd["Guzzanti"] = "Caterina"
# TypeError: 'frozendict' object doesn't support item assignment


"""create user_role table

Revision ID: 227d7972fc56
Revises: 40a51d118d42
Create Date: 2019-07-22 02:30:45.180876

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '227d7972fc56'
down_revision = '40a51d118d42'
branch_labels = None
depends_on = None

def upgrade():
    op.create_table(
        'role_user',
        sa.Column('user_id', sa.Integer, sa.ForeignKey('user.id')),
        sa.Column('role_id', sa.Integer, sa.ForeignKey('role.id'))
    )

def downgrade():
    op.drop_table('role_user')