import logging
import os
import pickle
from scipy import ndimage

import numpy
import tensorflow

logging.basicConfig(format='%(asctime)s : %(levelname)s :: %(message)s', level=logging.DEBUG)

# todo fix the image size; our images aren't square
image_size = 28  # Pixel width and height.
image_height = 28
image_width = 5 * 28
pixel_depth = 255.0  # Number of levels per pixel.

def load_letter(folder, min_num_images):
    """Load the data for a single letter label."""
    image_files = os.listdir(folder)
    dataset = numpy.ndarray(shape=(len(image_files), image_height, image_width), dtype=numpy.float32)
    logging.debug(folder)
    correct_values = []
    num_images = 0
    for image in image_files:
        correct_value = image.split('.')[0].split('_')[1]
        correct_values.append(correct_value)
        image_file = os.path.join(folder, image)
        try:
            image_data = (ndimage.imread(image_file).astype(float) - pixel_depth / 2) / pixel_depth
            if image_data.shape != (image_height, image_width):
                raise Exception('Unexpected image shape: %s' % str(image_data.shape))
            dataset[num_images, :, :] = image_data
            num_images += 1
        except IOError as e:
            logging.warn('Could not read: %s : %s - it\'s ok, skipping.' % (image_file, e))

    logging.debug('correct values: %s' % correct_values)
    dataset = dataset[0:num_images, :, :]
    if num_images < min_num_images:
        raise Exception('Many fewer images than expected: %d < %d' %
                        (num_images, min_num_images))

    logging.debug('Full dataset tensor: %s' % str(dataset.shape))
    logging.debug('Mean: %s' % numpy.mean(dataset))
    logging.debug('Standard deviation: %s' % numpy.std(dataset))
    return dataset, correct_values

def maybe_pickle(data_folders, min_num_images_per_class, force=False):
    dataset_names = []
    for folder in data_folders:
        set_filename = folder + '.pickle'
        dataset_names.append(set_filename)
        if os.path.exists(set_filename) and not force:
            # You may override by setting force=True.
            logging.debug('%s already present - Skipping pickling.' % set_filename)
        else:
            logging.debug('Pickling %s.' % set_filename)
            dataset, correct_values = load_letter(folder, min_num_images_per_class)
            try:
                with open(set_filename, 'wb') as f:
                    pickle.dump([dataset, correct_values], f, pickle.HIGHEST_PROTOCOL)

            except Exception as e:
                logging.warn('Unable to save data to', set_filename, ':', e)

    return dataset_names

def make_arrays(nb_rows, arg_image_height, arg_image_width):
    if nb_rows:
        dataset = numpy.ndarray((nb_rows, arg_image_height, arg_image_width), dtype=numpy.float32)
        labels = numpy.ndarray(nb_rows, dtype=numpy.int32)
    else:
        dataset, labels = None, None
    return dataset, labels

# todo split labels into 5 one-hot result sets
def split_data(arg_pickle_file_name, arg_train_size, arg_validation_size, arg_test_size, arg_image_height,
               arg_image_width):
    logging.debug(arg_pickle_file_name)
    with open(arg_pickle_file_name, 'rb') as f:
        letter_set, correct_values = pickle.load(f)
        state = numpy.random.get_state()
        numpy.random.shuffle(letter_set)
        numpy.random.set_state(state)
        numpy.random.shuffle(correct_values)
    start_train = 0
    end_train = start_train + arg_train_size
    start_validation = arg_train_size
    end_validation = start_validation + arg_validation_size
    start_test = arg_train_size + arg_validation_size
    end_test = start_test + arg_test_size
    result_train_data = numpy.ndarray((end_train - start_train + 1, arg_image_height, arg_image_width),
                                      dtype=numpy.float32)
    result_train_data[0:end_train - start_train] = letter_set[start_train:end_train]
    result_train_correct = correct_values[start_train:end_train]

    result_validation_data = numpy.ndarray((end_validation - start_validation + 1, arg_image_height, arg_image_width),
                                           dtype=numpy.float32)
    result_validation_data[0:end_validation - start_validation] = letter_set[start_validation:end_validation]
    result_validation_correct = correct_values[start_validation:end_validation]

    result_test_data = numpy.ndarray((end_test - start_test + 1, arg_image_height, arg_image_width),
                                     dtype=numpy.float32)
    result_test_data[0:end_test - start_test] = letter_set[start_test:end_test]
    result_test_correct = correct_values[start_test:end_test]

    return result_train_data, result_train_correct, result_validation_data, result_validation_correct, \
           result_test_data, result_test_correct

def special_ord(arg, arg_index):
    char = arg[arg_index]
    result = ord(char)
    result = result if result != 32 else 64
    result -= 64
    return result

vector_special_ord = numpy.vectorize(special_ord)

def reformat_as_list(dataset, arg_labels, arg_num_labels, arg_image_height, arg_image_width):
    dataset = dataset.reshape((-1, arg_image_height * arg_image_width)).astype(numpy.float32)
    # Map 0 to [1.0, 0.0, 0.0 ...], 1 to [0.0, 1.0, 0.0 ...]
    size = len(arg_labels)
    result = []
    for index in range(0, 5):
        t0 = vector_special_ord(arg_labels, 0)
        t1 = numpy.zeros((size, 11))
        t1[numpy.arange(size), t0] = 1
        result.append(t1)

    return dataset, result

def reformat(dataset, arg_labels, arg_num_labels, arg_image_height, arg_image_width):
    dataset = dataset.reshape((-1, arg_image_height * arg_image_width)).astype(numpy.float32)
    # Map 0 to [1.0, 0.0, 0.0 ...], 1 to [0.0, 1.0, 0.0 ...]
    size = len(arg_labels)
    # result = numpy.ndarray(shape=(5, arg_num_labels, 11))
    t2 = []
    for index in range(0, 5):
        t0 = vector_special_ord(arg_labels, 0)
        t1 = numpy.zeros((size, 11))
        t1[numpy.arange(size), t0] = 1
        t2.append(t1)
    result = numpy.asanyarray(t2)
    return dataset, result

def accuracy_old(predictions, labels):
    t0 = numpy.argmax(predictions, 1)
    t1 = numpy.argmax(labels, 1)
    t2 = t0 == t1
    t3 = numpy.sum(t2)
    result = 100.0 * t3 / predictions.shape[0]
    return result
    # return (100.0 * numpy.sum(numpy.argmax(predictions, 1) == numpy.argmax(labels, 1))
    #         / predictions.shape[0])

def accuracy(predictions, labels0, labels1, labels2, labels3, labels4):
    result = 0
    t0 = numpy.argmax(predictions[0], 1)
    t1 = numpy.argmax(labels0, 1)
    t2 = t0 == t1
    t3 = numpy.sum(t2)
    result += 100.0 * t3 / predictions[0].shape[0]
    t0 = numpy.argmax(predictions[1], 1)
    t1 = numpy.argmax(labels1, 1)
    t2 = t0 == t1
    t3 = numpy.sum(t2)
    result += 100.0 * t3 / predictions[1].shape[0]
    t0 = numpy.argmax(predictions[2], 1)
    t1 = numpy.argmax(labels2, 1)
    t2 = t0 == t1
    t3 = numpy.sum(t2)
    result += 100.0 * t3 / predictions[2].shape[0]
    t0 = numpy.argmax(predictions[3], 1)
    t1 = numpy.argmax(labels3, 1)
    t2 = t0 == t1
    t3 = numpy.sum(t2)
    result += 100.0 * t3 / predictions[3].shape[0]
    t0 = numpy.argmax(predictions[4], 1)
    t1 = numpy.argmax(labels4, 1)
    t2 = t0 == t1
    t3 = numpy.sum(t2)
    result += 100.0 * t3 / predictions[4].shape[0]
    return result

def alt_accuracy(predictions, labels0, labels1, labels2, labels3, labels4):
    result = 0
    t0 = numpy.argmax(predictions[0])
    t1 = numpy.argmax(labels0, 1)
    t2 = t0 == t1
    t3 = numpy.sum(t2)
    result += 100.0 * t3 / predictions[0].shape[0]
    t0 = numpy.argmax(predictions[1], 1)
    t1 = numpy.argmax(labels1, 1)
    t2 = t0 == t1
    t3 = numpy.sum(t2)
    result += 100.0 * t3 / predictions[1].shape[0]
    t0 = numpy.argmax(predictions[2], 1)
    t1 = numpy.argmax(labels2, 1)
    t2 = t0 == t1
    t3 = numpy.sum(t2)
    result += 100.0 * t3 / predictions[2].shape[0]
    t0 = numpy.argmax(predictions[3], 1)
    t1 = numpy.argmax(labels3, 1)
    t2 = t0 == t1
    t3 = numpy.sum(t2)
    result += 100.0 * t3 / predictions[3].shape[0]
    t0 = numpy.argmax(predictions[4], 1)
    t1 = numpy.argmax(labels4, 1)
    t2 = t0 == t1
    t3 = numpy.sum(t2)
    result += 100.0 * t3 / predictions[4].shape[0]
    return result

pickle_file_name = maybe_pickle(['concatenate_output'], 1800)

with open('concatenate_output.pickle', 'rb') as file_pointer:
    t, _ = pickle.load(file_pointer)
    total_data = len(t)
validation_size = total_data / 20
test_size = total_data / 20
train_size = total_data - validation_size - test_size

train_data, train_labels, validation_data, validation_labels, test_data, test_labels = \
    split_data(pickle_file_name[0], train_size, validation_size, test_size, image_height, image_width)

logging.debug('Training: %d %d' % (len(train_data), len(train_labels)))
logging.debug('Validation: %d %d' % (len(validation_data), len(validation_labels)))
logging.debug('Testing: %d %d' % (len(test_data), len(test_labels)))

num_labels = 11
train_dataset, train_labels = reformat(train_data, train_labels, num_labels, image_height, image_width)
valid_dataset, valid_labels = reformat(validation_data, validation_labels, num_labels, image_height, image_width)
test_dataset, test_labels = reformat(test_data, test_labels, num_labels, image_height, image_width)
logging.info('Training set: %s %s' % (train_dataset.shape, train_labels.shape))  # was train_labels[0].shape
logging.info('Validation set: %s %s' % (valid_dataset.shape, valid_labels.shape))
logging.debug('Test set: %s %s ' % (test_dataset.shape, test_labels.shape))
batch_size = 128

# With gradient descent training, even this much data is prohibitive.
# Subset the training data for faster turnaround.
train_subset = 10000

graph = tensorflow.Graph()
with graph.as_default():
    tf_train_dataset = tensorflow.placeholder(tensorflow.float32, shape=(batch_size, image_height * image_width))
    tf_train_labels0 = tensorflow.placeholder(tensorflow.float32, shape=(batch_size, num_labels))
    tf_train_labels1 = tensorflow.placeholder(tensorflow.float32, shape=(batch_size, num_labels))
    tf_train_labels2 = tensorflow.placeholder(tensorflow.float32, shape=(batch_size, num_labels))
    tf_train_labels3 = tensorflow.placeholder(tensorflow.float32, shape=(batch_size, num_labels))
    tf_train_labels4 = tensorflow.placeholder(tensorflow.float32, shape=(batch_size, num_labels))
    tf_valid_dataset = tensorflow.constant(valid_dataset)
    tf_test_dataset = tensorflow.constant(test_dataset)
    weights = tensorflow.Variable(tensorflow.truncated_normal([image_height * image_width, num_labels]))

    biases0 = tensorflow.Variable(tensorflow.zeros([num_labels]))
    logits0 = tensorflow.matmul(tf_train_dataset, weights) + biases0
    biases1 = tensorflow.Variable(tensorflow.zeros([num_labels]))
    logits1 = tensorflow.matmul(tf_train_dataset, weights) + biases1
    biases2 = tensorflow.Variable(tensorflow.zeros([num_labels]))
    logits2 = tensorflow.matmul(tf_train_dataset, weights) + biases2
    biases3 = tensorflow.Variable(tensorflow.zeros([num_labels]))
    logits3 = tensorflow.matmul(tf_train_dataset, weights) + biases3
    biases4 = tensorflow.Variable(tensorflow.zeros([num_labels]))
    logits4 = tensorflow.matmul(tf_train_dataset, weights) + biases4

    loss = \
        tensorflow.reduce_mean(tensorflow.nn.softmax_cross_entropy_with_logits(logits0, tf_train_labels0)) + \
        tensorflow.reduce_mean(tensorflow.nn.softmax_cross_entropy_with_logits(logits1, tf_train_labels1)) + \
        tensorflow.reduce_mean(tensorflow.nn.softmax_cross_entropy_with_logits(logits2, tf_train_labels2)) + \
        tensorflow.reduce_mean(tensorflow.nn.softmax_cross_entropy_with_logits(logits3, tf_train_labels3)) + \
        tensorflow.reduce_mean(tensorflow.nn.softmax_cross_entropy_with_logits(logits4, tf_train_labels4))

    optimizer = tensorflow.train.GradientDescentOptimizer(0.5).minimize(loss)
    train_prediction0 = tensorflow.nn.softmax(logits0)
    train_prediction1 = tensorflow.nn.softmax(logits1)
    train_prediction2 = tensorflow.nn.softmax(logits2)
    train_prediction3 = tensorflow.nn.softmax(logits3)
    train_prediction4 = tensorflow.nn.softmax(logits4)
    train_prediction = tensorflow.pack(
        [train_prediction0, train_prediction1, train_prediction2, train_prediction3, train_prediction4])
    # todo expand this out to 5 softmax calls just like the above
    valid_prediction = numpy.asanyarray([
        tensorflow.nn.softmax(tensorflow.matmul(tf_valid_dataset, weights) + biases0),
        tensorflow.nn.softmax(tensorflow.matmul(tf_valid_dataset, weights) + biases1),
        tensorflow.nn.softmax(tensorflow.matmul(tf_valid_dataset, weights) + biases2),
        tensorflow.nn.softmax(tensorflow.matmul(tf_valid_dataset, weights) + biases3),
        tensorflow.nn.softmax(tensorflow.matmul(tf_valid_dataset, weights) + biases4)]),

    test_prediction = tensorflow.pack([

        tensorflow.nn.softmax(tensorflow.matmul(tf_test_dataset, weights) + biases0),
        tensorflow.nn.softmax(tensorflow.matmul(tf_test_dataset, weights) + biases1),
        tensorflow.nn.softmax(tensorflow.matmul(tf_test_dataset, weights) + biases2),
        tensorflow.nn.softmax(tensorflow.matmul(tf_test_dataset, weights) + biases3),
        tensorflow.nn.softmax(tensorflow.matmul(tf_test_dataset, weights) + biases4)])

num_steps = 10001  # 3001

with tensorflow.Session(graph=graph, config=tensorflow.ConfigProto(device_count={'GPU': 0})) as session:
    tensorflow.global_variables_initializer().run()
    logging.debug("Initialized.")
    for step in range(num_steps):
        offset = (step * batch_size) % (train_labels[0].shape[0] - batch_size)
        # Generate a minibatch.
        batch_data = train_dataset[offset:(offset + batch_size), :]
        batch_labels0 = train_labels[0][offset:(offset + batch_size), :]
        batch_labels1 = train_labels[1][offset:(offset + batch_size), :]
        batch_labels2 = train_labels[2][offset:(offset + batch_size), :]
        batch_labels3 = train_labels[3][offset:(offset + batch_size), :]
        batch_labels4 = train_labels[4][offset:(offset + batch_size), :]
        # Prepare a dictionary telling the session where to feed the minibatch.
        # The key of the dictionary is the placeholder node of the graph to be fed,
        # and the value is the numpy array to feed to it.
        feed_dict = {tf_train_dataset: batch_data, tf_train_labels0: batch_labels0, tf_train_labels1: batch_labels1,
                     tf_train_labels2: batch_labels2, tf_train_labels3: batch_labels3,
                     tf_train_labels4: batch_labels4}
        _, l, predictions = session.run([optimizer, loss, train_prediction], feed_dict=feed_dict)
        if (step % 500 == 0):
            logging.info("Minibatch loss at step %d: %f" % (step, l))
            logging.info("Minibatch accuracy: %.1f%%" % accuracy(predictions, batch_labels0, batch_labels1,
                                                                 batch_labels2, batch_labels3, batch_labels4))
            # logging.info("Validation accuracy: %.1f%%" % accuracy(valid_prediction.eval(), valid_labels[0],
            logging.info("Validation accuracy: %.1f%%" % alt_accuracy(valid_prediction, valid_labels[0],
                                                                      valid_labels[1], valid_labels[2], valid_labels[3],
                                                                      valid_labels[4]))
    logging.info(
        "Test accuracy: %.1f%%" % accuracy(test_prediction.eval(), test_labels[0], test_labels[1], test_labels[2],
                                           test_labels[3], test_labels[4]))

# with tensorflow.Session(graph=graph, config=tensorflow.ConfigProto(device_count={'GPU': 0})) as session:
#     tensorflow.global_variables_initializer().run()
#     print('Initialized.')
#     for step in range(num_steps):
#         # Run the computations. We tell .run() that we want to run the optimizer,
#         # and get the loss value and the training predictions returned as numpy arrays
#         _, l, predictions = session.run([optimizer, loss, train_prediction])
#         if (step % 100 == 0):
#             print('Loss at step %d: %f' % (step, l))
#             print('Training accuracy: %.1f%%' % accuracy(predictions, train_labels[:train_subset, :]))
#             # Calling .eval() on valid_prediction is basically like calling run(), but
#             # just to get that one numpy array. Note that it recomputes all its graph
#             # dependencies.
#             print('Validation accuracy: %.1f%%' % accuracy(valid_prediction.eval(), valid_labels[0]))
#     print('Test accuracy: %.1f%%' % accuracy(test_prediction.eval(), test_labels))


import matplotlib.pyplot as plt
import unittest
import numpy as np
import smuthi
import smuthi.simulation
import smuthi.initial_field
import smuthi.layers
import smuthi.particles
import smuthi.postprocessing.far_field as ff
import smuthi.utility.optical_constants as opt
import io
import yaml

# for single wavelength
def get_extinctions(wavelength, sphere_refractive_index,
                    layers_thicknesses, layers_refractive_indeces, polarization, radius):
    spacer = 10  # nm

    layers = smuthi.layers.LayerSystem(thicknesses=layers_thicknesses,
                                       refractive_indices=layers_refractive_indeces)

    # Scattering particle
    sphere = smuthi.particles.Sphere(position=[0, 0, -radius - spacer],
                                     refractive_index=sphere_refractive_index,
                                     radius=radius,
                                     l_max=3)

    # list of all scattering particles (only one in this case)
    spheres_list = [sphere]

    # Initial field
    plane_wave = smuthi.initial_field.PlaneWave(vacuum_wavelength=wavelength,
                                                polar_angle=(25 * np.pi / 180),  # 25 grad to the surface
                                                azimuthal_angle=0,
                                                polarization=polarization)  # 0=TE 1=TM

    # Initialize and run simulation
    simulation = smuthi.simulation.Simulation(layer_system=layers,
                                              particle_list=spheres_list,
                                              initial_field=plane_wave,
                                              solver_type='LU',
                                              solver_tolerance=1e-5,
                                              store_coupling_matrix=True,
                                              coupling_matrix_lookup_resolution=None,
                                              coupling_matrix_interpolator_kind='cubic')
    simulation.run()

    # Since this moment we calculate extinction
    # Calculate total extinction
    general_ecs = ff.extinction_cross_section(initial_field=plane_wave,
                                              particle_list=spheres_list,
                                              layer_system=layers, only_pol=polarization)

    extinctions = [[], [[],[]], [[],[]]]
    # ord - order of multipole (1 - dipole, 2 - quadrupole)
    # extinctions[ord][0] -- magnetic projections,
    # extinctions[ord][1] -- electric projections
    # extinctions[0] -- total extinction
    for order in [1,2]:
        for tau in [0, 1]:
            calculated_extinction = ff.extinction_cross_section(initial_field=plane_wave,
                                                                    particle_list=spheres_list,
                                                                    layer_system=layers, only_l=order, only_pol=polarization,
                                                                    only_tau=tau)
            extinctions[order][tau].append(calculated_extinction)
    extinctions[0].append(general_ecs)

    return extinctions

def add_extinctions_to_output(wavelengths, extinctions, subplot, radius,
                              color_for_electric, color_for_magnetic):
    Q_ED = np.zeros(len(extinctions))
    Q_MD = np.zeros(len(extinctions))
    Q_EQ = np.zeros(len(extinctions))
    Q_MQ = np.zeros(len(extinctions))
    total = np.zeros(len(extinctions))

    # Here we convert extinction from spherical to cartesian projection.
    for i in range(len(extinctions)):
        Q_ED[i]=(extinctions[i][1][0][0]).real/np.pi/radius**2
        Q_MD[i] = (extinctions[i][1][1][0]).real/np.pi/radius**2
        Q_EQ[i] = (extinctions[i][2][0][0]).real/np.pi/radius**2
        Q_MQ[i] = (extinctions[i][2][1][0]).real/np.pi/radius**2
        total[i] = (extinctions[i][0][0]).real/np.pi/radius**2

    subplot.plot(wavelengths, Q_ED, color=color_for_electric, label='$\sigma_{ED}$')
    subplot.plot(wavelengths, Q_MD, color=color_for_magnetic, label='$\sigma_{MD}$')
    subplot.plot(wavelengths, Q_EQ, linestyle='dashed', color=color_for_electric, label='$\sigma_{EQ}$')
    subplot.plot(wavelengths, Q_MQ, linestyle='dashed', color=color_for_magnetic, label='$\sigma_{MQ}$')
    subplot.plot(wavelengths, total, color='black', label='$\sigma_{tot}$')
    subplot.legend()

wavelength_min = 500
wavelength_max = 1100
total_points = 300
wavelengths = np.linspace(wavelength_min, wavelength_max, total_points)

index_Si = opt.read_refractive_index_from_yaml('Si_Green-2008.yml', wavelengths, units="nm")
index_Au = opt.read_refractive_index_from_yaml('Au_refractive_index.yml', wavelengths, units="nm")

index_media = 1.0
radius = 129
Au_thickness = 300

extinctions_tm_gold = []

for i in range(len(wavelengths)):

    # With gold, TM polarization
    decomposed_tm_gold_extinction = get_extinctions(wavelengths[i], index_Si[i][1],
                                                    [0, Au_thickness, 0], [index_media, index_Au[i][1], index_media], 1,
                                                    radius)
    extinctions_tm_gold.append(decomposed_tm_gold_extinction)

# Since this moment we just output the calculated extinction decompositions.
f, ax_1 = plt.subplots(1, 1, sharex=True)

plt.annotate(text="TM", xy=(0.5, 0.9), xycoords='figure fraction')

add_extinctions_to_output(wavelengths, extinctions_tm_gold, ax_1, radius, 'red', 'blue')
ax_1.set_ylim(ymin=-5, ymax=25)
plt.show()


import tweepy
import os

consumer_key = os.environ.get('CUTIESINSF_CONSUMER_KEY')
consumer_secret = os.environ.get('CUTIESINSF_CONSUMER_SECRET')
access_token = os.environ.get('CUTIESINSF_ACCESS_TOKEN')
access_token_secret = os.environ.get('CUTIESINSF_ACCESS_TOKEN_SECRET')

class TweetPoster(object):

    def __init__(self):
        auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
        auth.set_access_token(access_token, access_token_secret)
        self.api = tweepy.API(auth)

    def post_tweet(self, text, image=None):
        self.status_count = self.api.me().statuses_count
        if self.status_count % 30 == 0:
            status = ('I\'m a bot that tweets about pets available for '
                      'at sfspca.org You can find my source code at '
                      'github.com/ecalifornica/CutePetsSF')
            tweet = self.api.update_status(status)
        elif image:
            image = str(image)
            tweet = self.api.update_with_media(image, text)
        else:
            tweet = self.api.update_status(text)

        return tweet.id

    def follow_followers(self):
        pass

    def about_bot(self):
        return self.api.me()


import numpy as np
import cv2
import matplotlib.pyplot as plt
import torch
import AENetwork
from cfg import DefaultConfig
# import time

torch.backends.cudnn.deterministic = True  # 因为使用了GPU，需要保证种子固定才能保证每次结果相同
torch.backends.cudnn.benchmark = True  # 让cuDNN找到最合适的算法
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(device)

model = AENetwork.AENetwork()
model.eval()  # 不使用BN和dropout，因为测试batch太小，会被BN和dropout影响
model.load_state_dict(torch.load(DefaultConfig.load_model_path + 'network_model.pth'))  # 读模型
model.to(device)

# 读取图像进行预处理，转换为tensor
image_path = r'./data/bottle//test/defect/295.jpg'
img = cv2.imread(image_path)
image = cv2.resize(img, (256, 256))
image_resized = (image.astype('float32') / 127.5) - 1.0  # to -1 ~ 1
image_resized = np.transpose(image_resized, [2, 0, 1])
input_tensor = torch.from_numpy(image_resized).to(device).unsqueeze(0)

output_image = model(input_tensor)
# 需要优化
# output_image = output_image.clone().squeeze(0).cpu().detach().numpy()
output_image = output_image.clone().squeeze(0).detach().cpu().numpy()
cv2_frame = ((output_image + 1) * 127.5).transpose(1, 2, 0).astype('uint8')

# 图像求差得到缺陷图
res_image = cv2.cvtColor(np.power(cv2.subtract(cv2_frame, image), 1), cv2.COLOR_BGR2GRAY)
res_image = cv2.medianBlur(res_image, 3)

# 打印结果
# plt.rcParams['font.sans-serif'] = ['SimHei']
# plt.rcParams['axes.unicode_minus'] = False  # 输出中文字体
# plt.figure(figsize=(19, 19))
# plt.subplot(1, 3, 1)
# plt.imshow(image)
# plt.title('原始图像')
# plt.subplot(1, 3, 2)
# plt.imshow(cv2_frame)
# plt.title('重构图像')
# plt.subplot(1, 3, 3)
# plt.imshow(res_image)
# plt.title('残差图像')
# plt.show()

# cost 0.030434608459472656 s
# cost 0.1248326301574707 s
# cost 0.007006168365478516 s
# cost 2.6321322917938232 s
# cost 0.0009963512420654297 s

plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False  # 输出中文字体
plt.figure(figsize=(19, 19))
plt.subplot(2, 1, 1)
plt.imshow(image)
plt.title('原始图像')
plt.subplot(2, 1, 2)
plt.imshow(res_image)
plt.title('残差图像')
plt.show()


# author:JinMing time:2020-06-02
# -*- coding: utf-8 -*-
from tc_data_env.nodata.course import *
from tc_data_env.nodata import *

teacherid = None

def setup():
    print('开始执行添加老师初始化')
    delete_all_teacher()

def teardown():
    print('开始执行添加老师清除')
    delete_teacher(teacherid)

def test_add_teacher():
    print('开始执行添加老师初用例')
    course = get_course()
    global teacherid
    res = add_teacher('kongzi', '123456', '孔子', '语文老师', course, 1)
    assert res['retcode'] == 0
    teacherid = res['id']


import torch
from torch.autograd import Variable
from torch.utils.data import TensorDataset, DataLoader

import numpy as np

def to_Variables(*args, cuda=False):
    ret = []
    for arg in args:
        if cuda:
            ret.append(Variable(arg).cuda())
        else:
            ret.append(Variable(arg))

    return ret

def check_and_convert_tensor(x):
    if torch.is_tensor(x):
        return x.cpu().numpy()
    else:
        return x.data.cpu().numpy()

n_features = 11
n_samples = 250
n_classes = 2

# Should give us a random label vector with entries 1 and -1
test_labels = torch.ones(n_samples).long()
test_labels[torch.ones(test_labels.shape).uniform_() > 0.5] = -1

# Generate random test data
test_data = torch.rand(n_samples, n_features).double()

# s indices
s = [8]

# Convert the 8th column of x to be categorical
l = torch.ones(test_data[:, s[0]].shape).uniform_()
test_data[:, s[0]] = 2
test_data[:, s[0]][l < 0.67] = 1
test_data[:, s[0]][l < 0.33] = 0

# Conversions to variables for use inside of everything
x = Variable(test_data).double()
y = Variable(test_labels).long()

# Generate random weights
w = Variable(torch.rand(n_features, 1)).double()

# Convert the data into a torch dataset
ds = TensorDataset(test_data, test_labels)
dl = DataLoader(ds, batch_size=32, shuffle=True)

# Enumerate through the data
for i, data in enumerate(dl):
    inputs, labels = to_Variables(*data)
    dtype = type(inputs.data)

    # Build up the indices
    fairness_idxs = []
    vals = []
    divisors = []
    for col in s:
        vals.append(np.unique(check_and_convert_tensor(test_data)[:, col]))
        fairness_idxs.append([])
        prod = 1
        for val in vals[-1]:
            idxs = (test_data[:, col] == float(val)).nonzero().squeeze()
            prod *= len(idxs)
            fairness_idxs[-1].append(idxs)
        divisors.append(prod)

    # Actually calculate the penalty
    penalty = 0
    for idxs, val, div in zip(fairness_idxs, vals, divisors):
        # Should be size (n_classes test_data self.minibatch_size)
        local_dots = torch.mm(inputs, w)
        for idx in idxs:
            # Because of broadcasting rules, this should create a matrix of absolute differences
            # of size (self.minibatch_size test_data |S_i: class[idx]|)
            diff = torch.abs(labels.view(1, -1) - y[idx].view(-1, 1)).type(dtype)

            # Size: (n_classes test_data |S_i: class[idx]|)
            non_local_dot = torch.mm(x[idx], w)

            cross_term = 0
            for local_dot in local_dots.t():
                # Individual version
                cross_term = cross_term + (local_dot - non_local_dot) ** 2
                penalty = penalty + ((diff / div) * cross_term).sum()

                # # Group version
                # cross_term = cross_term + (local_dot - non_local_dot)
                # penalty = penalty + ((diff / div) * cross_term).sum() ** 2

    print(penalty)


from PIL import Image
from pytesseract import pytesseract, Output
import os
import spacy
import cv2
import streamlit as st

pytesseract.tesseract_cmd = r"C:/Program Files/Tesseract-OCR/tesseract.exe"

def img_to_txt(file_name):
    img = Image.open(file_name)
    print('image is loaded')
    text = pytesseract.image_to_string(file_name)
    return text

def gene_interest():
    file_name = os.path.basename(filename).split('.')[0]
    if '_' in file_name:
        underscore_index = file_name.index('_')
        file_name = file_name[:underscore_index]
    print(file_name)

def extract_keywords(text):
    gene_interest()
    line_list = []
    result_index = 0
    paragraphs = text.split('\n\n')
    for line in paragraphs:
        if ('result' or 'summary') in line.lower():
            result_index = paragraphs.index(line)
            break
    results = paragraphs[result_index:]
    results_paragraphs = '\n\n'.join(results)
    nlp = spacy.load("en_ner_bionlp13cg_md")
    if results_paragraphs != []:
        doc = nlp(results_paragraphs)
    else:
        doc = nlp(text)
    words = doc.ents
    keywords = list(words)
    keyword_strings = []
    for item in keywords:
        keyword_strings.append(str(item).rstrip())
    keyword_strings = list(dict.fromkeys(keyword_strings))
    return keyword_strings

def check_similarity(a, b):
    chars_to_remove = "1ltLT"
    for char in chars_to_remove:
        a = a.replace(char, "")
        b = b.replace(char, "")
    if (a in b):
        return True
    return False

def label_image(file_name):
    gene_name = os.path.basename(file_name).split(".")[0].split("_")[0]

    # Check if found
    found = False
    img = cv2.imread(file_name)
    d = pytesseract.image_to_data(img, output_type=Output.DICT)
    keys = list(d.keys())

    # Iterate
    n_boxes = len(d['text'])
    for i in range(n_boxes):
        if check_similarity(gene_name, d['text'][i]):
            found = True
            (x, y, w, h) = (d['left'][i], d['top'][i], d['width'][i], d['height'][i])
            img = cv2.rectangle(img, (x - 6, y - 6), (x + w + 9, y + h + 9), (0, 255, 0), 2)

    if (found == False):
        font = cv2.FONT_HERSHEY_SIMPLEX
        img = cv2.putText(img,'No gene was found on report',(100,500), font, 2, (255, 0, 0), 2, cv2.LINE_AA)

    cv2.imwrite('output.png', img) # Modify this
    return found

def file_selector(folder_path='.'):
    filenames = os.listdir(folder_path)
    selected_filename = st.selectbox("Select a file", filenames)
    return os.path.join(folder_path, selected_filename)

if __name__ == '__main__':
    if st.checkbox("select a file in current directory"):
        folder_path = '.'
        if st.checkbox('Change directory'):
            folder_path = st.text_input('Enter folder path')
        filename = file_selector(folder_path=folder_path)
        image = Image.open(filename)
        st.write('You selected `%s`' % filename)
        label = label_image(filename)
        if label is True:
            label = "your target gene is present in the report."
        else:
            label = "Your target gene is not present in the report."
        st.image('output.png', caption=label)
        keyword_text = "Here are the keywords that might be helpful:"
        st.text(keyword_text)
        st.text(extract_keywords(img_to_txt(filename)))


import tensorflow as tf
import numpy as np
import os
import cifar10_input as c
from PIL import Image

cur_dir = os.getcwd()
print("resizing images")
print("current directory:",cur_dir)

def modify_image(image):
    flipped_images = tf.image.flip_up_down(image)
    return flipped_images

def read_image(filename_queue):
    reader = tf.WholeFileReader()
    key,value = reader.read(filename_queue)
    image = tf.image.decode_jpeg(value)
    return image

def inputs():
    filenames = ['/tmp/isic_dataset/bin_32_0.bin']
    filename_queue = tf.train.string_input_producer(filenames)
    read_input = c.read_cifar10(filename_queue)
    return modify_image(read_input.uint8image)

with tf.Graph().as_default():
    image = inputs()
    init = tf.initialize_all_variables()
    sess = tf.Session()
    sess.run(init)
    tf.train.start_queue_runners(sess=sess)
    for i in range(10):
        img = sess.run(image)
        img = Image.fromarray(img, "RGB")
        img.save(os.path.join(cur_dir,"foo"+str(i)+".jpeg"))


from yxsim.action import Action
from yxsim.cards.base import Card
from yxsim.player import Player
from yxsim.resources import Sect, Resource
from yxsim.combat import combat
import typing

class CardType(Card):
    display_name = 'Escape Plan'
    phase = 4
    sect = Sect.HEPTASTAR
    qi = 1

    def play(self, attacker: Player, defender: Player, **kwargs) -> Action:
        return Action(
            card=self,
            source=attacker,
            target=attacker,
            resource_changes={Resource.DEF: 9},
            healing=9,
            post_action=Action(card=self, source=attacker, target=attacker, resource_changes={Resource.GUARD_UP: 1})
        ).execute()

    def test_card(self):
        card_user, opponent = self.generate_test_data(player_kwargs={'health': 50, 'max_health': 100})
        combat(card_user, opponent, limit=1)
        assert card_user.health == 59
        assert card_user.resources[Resource.DEF] == 9

    def test_card_twice(self):
        card_user, opponent = self.generate_test_data()
        card_user.resources[Resource.PLAY_TWICE] = 1
        combat(card_user, opponent, limit=1)
        assert card_user.health == 68
        assert card_user.resources[Resource.DEF] == 18
        assert card_user.resources[Resource.GUARD_UP] == 1


n = int(input())
arr = list(map(int,input().split()))
m = int(input())

prefix = [0]*(n+1)
for i in range(n):
    prefix[i+1] = arr[i] + prefix[i]

amount = [0]*(n)

for i in range(n):
    if i+m <= n:
        amount[i] = prefix[i+m] - prefix[i]
    else:
        amount[i] = prefix[-1] - prefix[i]

dp = [[0]*n for _ in range(3)]
dp[0][0] = amount[0]

for i in range(1,n):
    dp[0][i] = max(dp[0][i-1], amount[i])

for i in range(1,3):
    for j in range(m*i,n):
        dp[i][j] = max(dp[i][j-1], dp[i-1][j-m]+amount[j])

# print(amount)
# for i in dp:
#     print(i)
print(dp[-1][-1])

4월 4주차/소형기관차.py


###############################################################################
#                                                                             #
#    This program is free software: you can redistribute it and/or modify     #
#    it under the terms of the GNU General Public License as published by     #
#    the Free Software Foundation, either version 3 of the License, or        #
#    (at your option) any later version.                                      #
#                                                                             #
#    This program is distributed in the hope that it will be useful,          #
#    but WITHOUT ANY WARRANTY; without even the implied warranty of           #
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the            #
#    GNU General Public License for more details.                             #
#                                                                             #
#    You should have received a copy of the GNU General Public License        #
#    along with this program. If not, see <http://www.gnu.org/licenses/>.     #
#                                                                             #
###############################################################################

import os
import sys
import logging
import shutil
import subprocess
import tempfile
import multiprocessing as mp

from unitem.seq_io import read_fasta, write_fasta
from unitem.utils import make_sure_path_exists

from numpy import (sum as np_sum, zeros as np_zeros, bool_ as np_bool)

AA_GENE_FILE_SUFFIX = '_genes.faa'
NT_GENE_FILE_SUFFIX = '_genes.fna'

class ProdigalException(Exception):
    """Exception for errors associated with running Prodigal."""

    def __init__(self, message=''):
        Exception.__init__(self, message)

class Prodigal(object):
    """Perform gene prediction using Prodigal."""

    def __init__(self, cpus):
        """Initialize."""

        self.logger = logging.getLogger('timestamp')

        self.cpus = cpus

    @staticmethod
    def version():
        try:
            proc = subprocess.Popen(['prodigal', '-v'],
                                    stderr=subprocess.PIPE,
                                    encoding='utf-8')

            _output, error = proc.communicate()

            return error.split('\n')[1].split()[1][1:-1]
        except:
            return "(version unavailable)"

    def _run_prodigal(self, gid, genome_file):
        """Run Prodigal."""

        # check if genome has previously been processed
        trans_table_file = os.path.join(
            self.output_dir,
            f'{gid}_translation_table.tsv')
        aa_gene_file = os.path.join(
            self.output_dir, f'{gid}{AA_GENE_FILE_SUFFIX}')
        nt_gene_file = os.path.join(
            self.output_dir, f'{gid}{NT_GENE_FILE_SUFFIX}')
        gff_file = os.path.join(self.output_dir, f'{gid}.gff')

        if (os.path.exists(trans_table_file)
            and os.path.exists(aa_gene_file)
            and os.path.exists(nt_gene_file)
                and os.path.exists(gff_file)):
            # use previously calculated results
            return aa_gene_file, nt_gene_file, gff_file, trans_table_file

        seqs = read_fasta(genome_file)

        if len(seqs) == 0:
            self.logger.warning(
                f'Cannot call Prodigal on empty genome: {genome_file}')
            return None

        with tempfile.TemporaryDirectory() as tmp_dir:

            # determine number of bases
            total_bases = sum(len(seq) for seq in seqs.values())

            # Prodigal requires an uncompressed FASTA file
            prodigal_input = genome_file
            if genome_file.endswith('.gz'):
                prodigal_input = os.path.join(tmp_dir, f'{gid}.fna')
                write_fasta(seqs, prodigal_input)

            # there may be ^M character in the input file,
            # the following code is similar to dos2unix command to remove
            # those special characters.
            with open(prodigal_input, 'r') as fh:
                text = fh.read().replace('\r\n', '\n')

            processed_prodigal_input = os.path.join(
                tmp_dir,
                os.path.basename(prodigal_input))
            with open(processed_prodigal_input, 'w') as fh:
                fh.write(text)

            # call genes under different translation tables
            table_coding_density = {4: -1, 11: -1}
            for trans_table in table_coding_density:
                tt_tmp_dir = os.path.join(tmp_dir, str(trans_table))
                os.makedirs(tt_tmp_dir)
                aa_gene_file_tmp = os.path.join(
                    tt_tmp_dir,
                    f'{gid}{AA_GENE_FILE_SUFFIX}')
                nt_gene_file_tmp = os.path.join(
                    tt_tmp_dir,
                    f'{gid}{NT_GENE_FILE_SUFFIX}')
                gff_file_tmp = os.path.join(tt_tmp_dir, gid + '.gff')

                # check if there is sufficient bases to calculate prodigal parameters
                cmd = ['prodigal', '-m', '-q', '-f', 'gff']
                if total_bases < 100000:
                    cmd += ['-p', 'meta']  # use best pre-calculated parameters
                else:
                    cmd += ['-p', 'single']  # estimate parameters from data

                cmd += ['-g', str(trans_table)]
                cmd += ['-a', str(aa_gene_file_tmp)]
                cmd += ['-d', str(nt_gene_file_tmp)]
                cmd += ['-i', str(processed_prodigal_input)]

                with open(gff_file_tmp, 'wb') as stdout:
                    proc = subprocess.Popen(cmd,
                                            stdout=stdout,
                                            encoding='utf-8')

                    proc.communicate()
                    exit_code = proc.wait()
                    if exit_code != 0:
                        self.logger.error(
                            'Prodigal returned non-zero exit code.')
                        self.logger.error(f'Skipping genome {gid}.')
                        return None

                prodigalParser = ProdigalGeneFeatureParser(gff_file_tmp)

                codingBases = 0
                for seq_id, _seq in seqs.items():
                    codingBases += prodigalParser.coding_bases(seq_id)

                codingDensity = float(codingBases) / total_bases
                table_coding_density[trans_table] = codingDensity

            # determine best translation table
            trans_table_out = open(trans_table_file, 'w')
            trans_table_out.write('Table\tCoding density\n')
            trans_table_out.write(f'4\t{table_coding_density[4]:.3f}\n')
            trans_table_out.write(f'11\t{table_coding_density[11]:.3f}\n')

            best_tt = 11
            if (table_coding_density[4] - table_coding_density[11] > 0.05) and table_coding_density[4] > 0.7:
                best_tt = 4

            trans_table_out.write(f'\nSelected table\t{best_tt}\n')

            # copy results for best translation table to desired output files
            best_tt_dir = os.path.join(tmp_dir, str(best_tt))
            shutil.copyfile(os.path.join(
                best_tt_dir, f'{gid}{AA_GENE_FILE_SUFFIX}'), aa_gene_file)
            shutil.copyfile(os.path.join(
                best_tt_dir, f'{gid}{NT_GENE_FILE_SUFFIX}'), nt_gene_file)
            shutil.copyfile(os.path.join(best_tt_dir, f'{gid}.gff'), gff_file)

        return aa_gene_file, nt_gene_file, gff_file, trans_table_file

    def _worker(self, out_dict, worker_queue, writer_queue):
        """Run Prodigal in parallel across genomes."""

        while True:
            data = worker_queue.get(block=True, timeout=None)
            if data is None:
                break

            gid, genome_file = data

            out_files = self._run_prodigal(gid, genome_file)

            # Only proceed if an error didn't occur when running Prodigal
            if out_files:
                prodigal_output = {"aa_gene_path": out_files[0],
                                   "nt_gene_path": out_files[1],
                                   "gff_path": out_files[2],
                                   "translation_table_path": out_files[3]}

                out_dict[gid] = prodigal_output

            writer_queue.put(gid)

    def _writer(self, num_genomes, writer_queue):
        """Track progress."""

        num_processed = 0
        while True:
            data = writer_queue.get(block=True, timeout=None)
            if data is None:
                break

            num_processed += 1
            status = f' -> processed {num_processed:,} of {num_genomes:,} genomes'
            sys.stdout.write(f'{status}\r')
            sys.stdout.flush()

    def run(self, genomic_files, output_dir):
        """Run Prodigal across a set of genomes."""

        self.output_dir = output_dir
        make_sure_path_exists(output_dir)

        # populate worker queue with data to process
        worker_queue = mp.Queue()
        writer_queue = mp.Queue()

        for gid, genome_file in genomic_files.items():
            worker_queue.put((gid, genome_file))

        for _ in range(self.cpus):
            worker_queue.put(None)

        worker_proc = []
        writer_proc = None
        try:
            manager = mp.Manager()
            out_dict = manager.dict()

            worker_proc = [mp.Process(target=self._worker, args=(out_dict,
                                                                 worker_queue,
                                                                 writer_queue))
                           for _ in range(self.cpus)]
            writer_proc = mp.Process(target=self._writer, args=(len(genomic_files),
                                                                writer_queue))

            writer_proc.start()
            for p in worker_proc:
                p.start()

            for p in worker_proc:
                p.join()

                # Gracefully terminate the program.
                if p.exitcode != 0:
                    raise ProdigalException(
                        'Prodigal returned non-zero exit code.')

            writer_queue.put(None)
            writer_proc.join()
        except Exception as e:
            for p in worker_proc:
                p.terminate()

            if writer_proc:
                writer_proc.terminate()

            raise ProdigalException(
                f'Exception caught while running Prodigal: {e}')

        # report genomes which failed to have any genes called
        result_dict = dict()
        failed_gids = list()
        for gid, gid_dict in out_dict.items():
            if os.path.getsize(gid_dict['aa_gene_path']) <= 1:
                failed_gids.append(gid)
            else:
                result_dict[gid] = gid_dict

        if len(failed_gids) > 0:
            self.logger.warning(f'Skipping {len(failed_gids)} of {len(genomic_files)} '
                                'genomes as no genes were called by Prodigal.')

        return result_dict

class ProdigalGeneFeatureParser(object):
    """Parses prodigal gene feature files (GFF) output."""

    def __init__(self, filename):
        """Initialization.

        Parameters
        ----------
        filename : str
            GFF file to parse.
        """

        self.genes = {}
        self.last_coding_base = {}

        self._parseGFF(filename)

        self.coding_base_masks = {}
        for seq_id in self.genes:
            self.coding_base_masks[seq_id] = self._build_coding_base_mask(
                seq_id)

    def _parseGFF(self, filename):
        """Parse genes from GFF file.

        Parameters
        ----------
        filename : str
            GFF file to parse.
        """
        bGetTranslationTable = True
        with open(filename, 'r') as fh:
            for line in fh:
                if bGetTranslationTable and line.startswith('# Model Data'):
                    data_model_info = line.split(':')[1].strip().split(';')
                    dict_data_model = {}
                    for item in data_model_info:
                        k = item.split('=')[0]
                        v = item.split('=')[1]
                        dict_data_model[k] = v

                    self.translationTable = int(
                        dict_data_model.get('transl_table'))
                    bGetTranslationTable = False

                if line[0] == '#':
                    continue

                line_split = line.split('\t')
                seq_id = line_split[0]
                if seq_id not in self.genes:
                    geneCounter = 0
                    self.genes[seq_id] = {}
                    self.last_coding_base[seq_id] = 0

                geneId = seq_id + '_' + str(geneCounter)
                geneCounter += 1
                start = int(line_split[3])
                end = int(line_split[4])

                self.genes[seq_id][geneId] = [start, end]
                self.last_coding_base[seq_id] = max(
                    self.last_coding_base[seq_id], end)

    def _build_coding_base_mask(self, seq_id):
        """Build mask indicating which bases in a sequences are coding.

        Parameters
        ----------
        seq_id : str
            Unique id of sequence.
        """

        # safe way to calculate coding bases as it accounts
        # for the potential of overlapping genes
        coding_base_mask = np_zeros(
            self.last_coding_base[seq_id], dtype=np_bool)
        for pos in self.genes[seq_id].values():
            coding_base_mask[pos[0]:pos[1] + 1] = True

        return coding_base_mask

    def coding_bases(self, seq_id, start=0, end=None):
        """Calculate number of coding bases in sequence between [start, end).

        To process the entire sequence set start to 0, and
        end to None.

        Parameters
        ----------
        seq_id : str
            Unique id of sequence.
        start : int
            Start calculation at this position in sequence.
        end : int
            End calculation just before this position in the sequence.
        """

        # check if sequence has any genes
        if seq_id not in self.genes:
            return 0

        # set end to last coding base if not specified
        if end is None:
            end = self.last_coding_base[seq_id]

        return np_sum(self.coding_base_masks[seq_id][start:end])


class BankAccount:
    def __init__(self, int_rate = 0.0345, balance = 100.0):
        self.rate = int_rate
        self.acctBalance = balance

    def deposit(self, amount):
        self.acctBalance += amount

    def withdraw(self, amount):
        self.acctBalance -= amount

    def display_account_info(self):
        print("Balance: ", self.acctBalance)

    # def getMonthlyInterestRate(self):
    #     return self.rate / 12

    def yield_interest(self):
        self.acctBalance += self.acctBalance * self.rate

bnkacct1 = BankAccount(0.0345, 150)
bnkacct2 = BankAccount(0.02355, 1000)

bnkacct1.deposit(150)
bnkacct1.deposit(200)
bnkacct1.deposit(300)
bnkacct1.withdraw(200)
bnkacct1.withdraw(150)
bnkacct2.deposit(200)
bnkacct2.deposit(150)
bnkacct2.withdraw(130)
bnkacct2.withdraw(250)
bnkacct2.withdraw(100)
bnkacct1.yield_interest()
bnkacct1.display_account_info()
bnkacct2.yield_interest()
bnkacct2.display_account_info()


import sys
from pathlib import Path
from typing import Any, Optional

import loguru
import loguru._logger

logger = loguru.logger

def setup_logger(
    output_dir: Optional[Path] = None,
    bind: dict[str, Any] = {},
    stderr_level: str = "INFO",
    file_level: str = "DEBUG",
    # ) -> "loguru.Logger":
) -> None:
    _logger = loguru.logger.bind(**bind)
    _logger.remove()
    format = (
        "<green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> | "
        "<level>{level: <8}</level> | "
        "<cyan>{name}</cyan>:<cyan>{function}</cyan>:<cyan>{line}</cyan>"
        " - <level>{message}</level>"
        " - {extra}"
    )
    _logger.add(sys.stdout, colorize=True, format=format, level=stderr_level)
    if output_dir is not None:
        _logger.add(
            output_dir / "output.log",
            backtrace=True,
            diagnose=True,
            format=format,
        )
        _logger.add(
            output_dir / "output.jsonl", serialize=True, level=file_level
        )
        _logger.info(f"Use logger output_dir: {str(output_dir)}")

    global logger
    logger = _logger


from src.utils.testmodelutils import test_models_on_batch_and_show
from src.utils.Metrics import auc, acc, highest_tpr_thresh, lowest_fpr_thresh
from src.utils.ParamTuner import ParamTuner
from src.utils.utils import init_folder, make_folder_if_not_there
from src.utils.Plotting import make_plot

from src.experiments.utils import get_resize_wrapper, get_pretrained_size_and_norm_wrapper

import torch

import os

def RunExpt(expt_name,
            model,
            model_kwargs,
            epochs,
            directories,
            augmented,
            wrapper=None,
            lrs=[0.003],
            bss=[64],
            opts=[torch.optim.Adam],
            losses=[torch.nn.BCELoss],
            workers=2,
            save_every=2,
            **kwargs):
    """
    Run an experiment
    Basically just bunch all the things I need together for hyperparam tuning so I dont have to always write it out
    also now we can wrap it up for different models aswell
    :param expt_name: the name of the experiment
    :param model:the class of the model to use for tuning
    :param model_kwargs: the arguments to pass to the model initialise
    :param epochs: the number of epochs to train for
    :param directories: a dictionary of the data, log, and checkpoint directories
    :param augmented: whether this experiment is using augmented data or not
    :param wrapper: a wrapper function for data loading if needed
    :param lrs: a list of learning rates to try length >= 1
    :param bss: a list of batch sizes to try length >= 1
    :param opts: a list of optimizers to try length >= 1
    :param losses: a list of loss functions to try length >= 1
    :param workers: the number of workers for dataloading to use
    :param save_every: how often to save the models and optimizers
    :param kwargs: the optional kwargs to pass to the param tuner
    """
    torch.cuda.empty_cache()

    DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    print(f"Using Device {DEVICE}")

    EPOCHS = epochs
    WORKERS = workers

    metrics_dict = {
        "auc": auc,
        "acc": acc,
        "top_tpr_thresh": highest_tpr_thresh,
        "low_fpr_thresh": lowest_fpr_thresh
    }

    log_dir = init_folder(f"{expt_name}", directories["log"], True)
    ckp_dir = init_folder(f"{expt_name}", directories["ckp"], True)

    tune = ParamTuner(expt_name,
                      model,
                      metrics_dict,
                      "auc",
                      directories["data"],
                      log_dir,
                      ckp_dir,
                      augmented,
                      model_kwargs=model_kwargs,
                      learning_rates=lrs,
                      batch_sizes=bss,
                      optimisers=opts,
                      losses=losses,
                      EPOCHS=EPOCHS,
                      wrapped_function=wrapper,
                      WORKERS=WORKERS,
                      SAVE_EVERY=save_every,
                      DEVICE=DEVICE,
                      verbose=True,
                      overwrite=True,
                      **kwargs)

    print(f"HYPER-PARAM OUTPUT: {tune.trials}")
    print(f"EXPERIMENT {expt_name} FINISHED")

    print("PLOTTING!")

    cwd = os.getcwd()
    fig_dir = make_folder_if_not_there("figs", cwd)
    tuned_fig_dir = init_folder(expt_name, fig_dir, True)
    make_plot(log_dir, tuned_fig_dir)

    test_data_path = ""
    if "test" in directories.keys():
        test_data_path = directories["test"]
    else:
        test_data_path = directories["data"]
    test_models_on_batch_and_show(expt_name, test_data_path, ckp_dir, model, model_kwargs, dev=DEVICE, wrapped=wrapper)

    torch.cuda.empty_cache()

def base_experiment(name,
                    model,
                    directories,
                    workers,
                    model_kwargs,
                    aug,
                    wrapper=None,
                    lrs=[0.1, 0.01, 0.001, 0.0001],
                    bss=[32, 64],
                    opts=[torch.optim.Adam],
                    losses=[torch.nn.BCELoss],
                    **kwargs):
    """
    Run a single experiment
    :param name: name of experiment
    :param model: the class of the model to use
    :param directories: a dictionary of the data, logs, and checkpoints
    :param workers: the number of workers to use for data loading
    :param model_kwargs: the arguments to pass to the model when initialized
    :param aug: wether ot not the data is augmented
    :param wrapper: Wrapper required
    :param lrs: The learning rates to try
    :param bss: The Batch Sizes to try
    :param opts: The Optimizers to try
    :param losses: The Loss Functions to try
    :param kwargs: the optional kwargs to pass to the param tuner
    """
    RunExpt(f"{name}_EXPT",
            model,
            model_kwargs,
            100,
            directories,
            aug,
            wrapper,
            lrs=lrs,
            bss=bss,
            opts=opts,
            losses=losses,
            workers=workers,
            save_every=10,
            **kwargs)

def regular_experiment(name,
                       model,
                       directories,
                       size,
                       workers,
                       model_kwargs,
                       aug,
                       lrs=[0.1, 0.01, 0.001, 0.0001],
                       bss=[32, 64],
                       opts=[torch.optim.Adam],
                       losses=[torch.nn.BCELoss],
                       **kwargs):
    """
    Run a single experiment on an untrained model
    :param name: name of experiment
    :param model: the class of the model to use
    :param directories: a dictionary of the data, logs, and checkpoints
    :param size: size to resize samples to
    :param workers: the number of workers to use for data loading
    :param model_kwargs: the arguments to pass to the model when initialized
    :param aug: wether ot not the data is augmented
    :param lrs: The learning rates to try
    :param bss: The Batch Sizes to try
    :param opts: The Optimizers to try
    :param losses: The Loss Functions to try
    :param kwargs: the optional kwargs to pass to the param tuner
    """
    wrapper = get_resize_wrapper(size)
    base_experiment(name, model, directories, workers, model_kwargs, aug, wrapper, lrs=lrs, bss=bss, opts=opts,
                    losses=losses, **kwargs)

def pretrained_experiment(name,
                          model,
                          directories,
                          size,
                          workers,
                          model_kwargs,
                          aug,
                          lrs=[0.1, 0.01, 0.001, 0.0001],
                          bss=[32, 64],
                          opts=[torch.optim.Adam],
                          losses=[torch.nn.BCELoss],
                          **kwargs):
    """
    Run a single experiment on a pretrained model
    :param name: name of experiment
    :param model: the class of the model to use
    :param directories: a dictionary of the data, logs, and checkpoints
    :param size: size to resize samples to
    :param workers: the number of workers to use for data loading
    :param model_kwargs: the arguments to pass to the model when initialized
    :param aug: wether ot not the data is augmented
    :param lrs: The learning rates to try
    :param bss: The Batch Sizes to try
    :param opts: The Optimizers to try
    :param losses: The Loss Functions to try
    :param kwargs: the optional kwargs to pass to the param tuner
    """
    wrapper = get_pretrained_size_and_norm_wrapper(size)
    base_experiment(name, model, directories, workers, model_kwargs, aug, wrapper, lrs=lrs, bss=bss, opts=opts,
                    losses=losses, **kwargs)


#!/usr/bin/env python3
"""
Usage: spack-gen-external-packages.py > /path/to/spack/etc/spack/packages.yaml

Requires python 3.3+

You can also save to ~/.spack/packages.yaml, but I prefer using the spack
dir because I typically keep multiple spack installs around and I don't
want them interfering with each other with common config.
"""

import sys
import subprocess
import shutil
import os.path

# spack names for packages
PACKAGES = [
  # build tools
  'autoconf', 'automake', 'bison', 'cmake', 'libtool', 'm4', 'flex',
  'pkg-config',

  # system utils
  'binutils', 'curl', 'gawk', 'diffutils', 'zsh',

  # compression
  'zlib', 'xz', 'tar', 'lz4', 'bzip2', 'snappy',

  # libs
  'openssl', 'gettext', 'ncurses', 'readline', 'gmp', 'libpng', 'libffi',
  'gdbm', 'expat', 'sqlite', 'libxml2',
]

RPM_NAME_MAP = {
    'pkg-config': 'pkgconfig',
    'bzip2': 'bzip2-dev',
    'gdbm': 'gdbm-dev',
    'expat': 'expat-dev',
    'sqlite': 'sqlite-dev',
    'libxml2': 'libxml2-dev',
}

DPKG_NAME_MAP = {
    'xz': 'liblzma-dev',
    'bzip2': 'libbz2-dev',
    'ncurses': 'libncurses-dev',
    'zlib': 'zlib1g-dev',
    'gmp': 'libgmp-dev',
    'readline': 'libreadline-dev',
    'libpng': 'libpng-dev',
    'libffi': 'libffi-dev',
    'snappy': 'libsnappy-dev',
    'gdbm': 'libgdbm-dev',
    'expat': 'libexpat1-dev',
    'sqlite': 'libsqlite3-dev',
    'libxml2': 'libxml2-dev',
}

# For packages that separate binary and dev library, it's common
# for only the binary to be installed. Don't use the binary
# version fallback method for these.
SKIP_BINARY_NAME = set([
   'bzip2'
])

def rpm_get_version(pkg_name):
    rpm_name = RPM_NAME_MAP.get(pkg_name, pkg_name)
    cmd = ['rpm', '-q', '--qf', '%{VERSION}', rpm_name]

    try:
        version_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
    except subprocess.CalledProcessError:
        return None

    version = version_output.splitlines()[0].decode('utf-8')
    return version

def _dpkg_to_spack_version(v):
    if '+' in v:
        # handle 1.1.1d-0+deb10u2 (openssl)
        parts = v.split('+')
        return parts[0]
    if ':' in v:
        # handle 4:8.3.0 (gcc)
        parts = v.split(':')
        return parts[1]
    return v

def dpkg_get_version(pkg_name):
    dpkg_name = DPKG_NAME_MAP.get(pkg_name, pkg_name)
    cmd = ['dpkg', '-s', dpkg_name]

    try:
        info_output = subprocess.check_output(cmd)
    except subprocess.CalledProcessError:
        return None

    installed = False
    version = None
    for line in info_output.splitlines():
        line = line.decode('utf-8')
        if line.startswith('Status:'):
            value = line[len('Status:'):].strip()
            parts = value.split()
            if 'installed' in parts:
                installed = True
            else:
                return None
        elif line.startswith('Version:'):
            value = line[len('Version:'):].strip()
            version = _dpkg_to_spack_version(value)
    if installed and version is not None:
        return version
    return None

yaml_format = """  {pkg_name}:
    paths:
      {pkg_name}@{pkg_version}%{compiler}: {path}
"""

yaml_format_no_compiler = """  {pkg_name}:
    paths:
      {pkg_name}@{pkg_version}: {path}
"""

def get_version_and_path(binary_name):
    """Fragile way to try to get version and basepath for a binary,
    use only if package system query fails."""
    binary_path = shutil.which(binary_name)
    if binary_path is None:
        return (None, None)

    cmd = [binary_path, '--version']

    version = None
    version_output = subprocess.check_output(cmd)
    version_line = version_output.splitlines()[0].decode('utf-8')
    for word in version_line.split():
        if word[0].isdigit():
            version = word
            break

    if version is None:
        print('version for %s not found' % binary_name)
        return

    # Path needed by spack is the parent of the bin dir
    root_dir = os.path.dirname(os.path.dirname(binary_path))

    return (version, root_dir)

def print_packages_yaml(pkg_name, compiler=None, pkg_fn=None, buildable=True):
    """Search if pkg exists in rpm database, if it does get the version
    number and parent directory name, and write spack packages.yaml config
    to stdout. Assumes all packages are in /usr
    """
    version = None
    if pkg_fn is not None:
        version = pkg_fn(pkg_name)
    if version is None:
        if pkg_name in SKIP_BINARY_NAME:
            return
        # for packages that happen to have same name as a command, try
        # to find the binary
        (version, path) = get_version_and_path(pkg_name)
        if version is None or path is None:
            return
    else:
        path = "/usr"

    if compiler is not None:
        print(yaml_format.format(pkg_name=pkg_name, pkg_version=version,
                                 compiler=compiler, path=path), end='')
    else:
        print(yaml_format_no_compiler.format(
                    pkg_name=pkg_name, pkg_version=version,
                    compiler=compiler, path=path),end='')
    if not buildable:
       print("    buildable: false")
    print()

def main():
    print("packages:")

    pkg_fn = None

    if os.path.exists('/etc/debian_version'):
        pkg_fn = dpkg_get_version
        gcc_version = dpkg_get_version("gcc")
    elif os.path.exists('/etc/redhat-release'):
        pkg_fn = rpm_get_version
        gcc_version = rpm_get_version("gcc")
    else:
        (gcc_version, _) = get_version_and_path('gcc')

    if gcc_version is None:
        print("Error: unable to find gcc version, exiting")
        sys.exit(1)

    compiler = "gcc@" + gcc_version

    # Note: specifying the compiler used to build external packages is
    # in theory a nice idea, however it has an unfortunate side effect
    # of encouraging spack to use the system compiler to build software
    # when it's dependencies are build with it, even when a newer compiler
    # is set as the default in concretization preferences in packages.yaml

    # setting buildable false can break things when a package requires
    # a new release. If spack is misbehaving and not properly favoring
    # already installed versions over new versions, we can try to
    # force the priority with lines like this:
    #    version: [{pkg_version}, "{pkg_version}:"]

    # List of binaries commonly found on a typical Linux system
    for pkg_name in PACKAGES:
        print_packages_yaml(pkg_name, compiler=None, pkg_fn=pkg_fn,
                            buildable=True)

if __name__ == '__main__':
    main()


import pytest
import allure

@allure.feature('omplogin-分销商登录')
class TestDemo8_omplogin(object):

    @allure.story('omp登录有效类')
    @allure.title('1111111111111')
    @allure.severity('Normal')
    @allure.step('输入正确的用户名和密码')
    def test_loginYXL(self):
        '''
        用例描述：输入正确的用户名和密码可正常登录
        '''
        print('我是有效类1111')
        assert 1==1

    @allure.story('omp登录无效类')
    @allure.title('2222222222222')
    @allure.severity('Critical')
    @allure.issue('http://www.baidu.com',name='链接地址')
    @allure.testcase('http://obp.888ly.cn',name='bug地址')
    @allure.step('输入错误的用户名和密码组合')
    def test_loginWXL(self):
        '''
        用例描述：用户名+密码 各种错误或者为空的组合验证
        '''
        with allure.step('输入用户名'):
            print('我是无效类1111')
        with allure.step('输入密码'):
            print('输入密码')
        with allure.step('输入错误的用户名{0}，输入正确的密码{1}'.format(None,'abc123')):
            print('33333333333')
        with open(r'C:\Users\suqiangqiang\Desktop\33.png','rb') as f:
            file=f.read()
            allure.attach(file,'登录无效类--用户名为空',allure.attachment_type.PNG)
        assert 1==1

if __name__ == "__main__":
   pytest.main(['-s',__file__,'--alluredir','Learning/pytest/report/'])


# l = []
# def Postfix(p):
#     d = p.split(",")
#     for i in range(len(d)):
#         if d[i] not in ['+', '-', '*', '/']:
#             l.append(int(d[i]))
#             # print(l)
#         else:
#             a = l.pop(l.index(l[-1]))
#             b = l.pop(l.index(l[-1]))

#             if d[i] == "+":
#                 sum = b + a
#                 l.append(sum)
#                 # print(l)

#             elif d[i] == "-":
#                 sum = b - a
#                 l.append(sum)
#                 # print(l)
#             elif d[i] == "*":
#                 sum = b * a
#                 l.append(sum)
#                 # print(l)
#             elif d[i] == "/":
#                 sum = b / a
#                 l.append(sum)
#                 # print(l)
#     print("Postfix is: ",int(l[0]))

# p = '5,6,2,+,*,12,4,/,-'
# Postfix(p)

def is_operand(c):
	return c.isdigit()

def evaluate(expression):
	stack = []

	for c in expression[::-1]:

		if is_operand(c):
			stack.append(int(c))

		else:
			o1 = stack.pop()
			o2 = stack.pop()

			if c == '+':
				stack.append(o1 + o2)

			elif c == '-':
				stack.append(o1 - o2)

			elif c == '*':
				stack.append(o1 * o2)

			elif c == '/':
				stack.append(o1 / o2)

	return stack.pop()

if __name__ == "__main__":
	test_expression = "+9*26"
	print(evaluate(test_expression))


from django.shortcuts import render, get_object_or_404, redirect
from .forms import QuestionForm, TestCreateForm
from Test_Designing.models import Test,QuestionSet,Question,StudentResult
from Result_Analysis.models import Teacher,Student
from django.contrib import messages
from django.forms import formset_factory
from django.http import HttpResponse
import random
from django.contrib.auth.decorators import user_passes_test, login_required
import datetime
from django.utils import timezone

'''  Utility Functions   '''

def check_teacher(user):
    try:
        Teacher.objects.get(teacher=user)
        return True
    except:
        return False

def check_student(user):
    try:
        Student.objects.get(student=user)
        return True
    except:
        return False

'''        end          '''

def index(request):
    return render(request,'Test_Designing/exam.html')

def exam_error(request):
    return render(request, 'Test_Designing/exam/exam_error.html')

@login_required(login_url='result:login')
@user_passes_test(check_teacher, login_url='/test/error')
def design(request):
    test_form = TestCreateForm()
    question_formset = formset_factory(QuestionForm)
    question_formset_post = question_formset(request.POST or None)

    if request.method == 'POST':

        total_marks = 0

        test_form = TestCreateForm(request.POST)
        question_formset_post = question_formset(request.POST)

        if test_form.is_valid() and question_formset_post.is_valid():

            teacher = Teacher.objects.get(teacher=request.user)

            testList = test_form.save(commit=False)
            testList.teacher = teacher
            testList.save()

            questionList = QuestionSet.objects.create(question_list=testList)

            for question in question_formset_post:

                questionInstance = question.save(commit=False)
                questionInstance.question = questionList
                questionInstance.save()

                total_marks = total_marks + questionInstance.mark

            testList.total_marks = total_marks
            testList.save()
            messages.success(request, 'Test Created Successfully')
            return redirect('result:dashboard')

        else:
            context = {
                'test_form':test_form,
                'question_formset':question_formset_post
            }
            return render(request, 'Test_Designing/exam_set.html', context)

    context = {
        'test_form': test_form,
        'question_formset': question_formset
    }
    return render(request, 'Test_Designing/exam_set.html', context)

#exam_taking views starts here

@login_required(login_url='result:login')
@user_passes_test(check_student, login_url='/test/error')
def exam_form(request):
    return render(request,'Test_Designing/quiz-form.html')

@login_required(login_url='result:login')
@user_passes_test(check_student, login_url='/test/error')
def exam(request):
    testid = request.POST['exam-name']
    posts = Question.objects.filter(question__question_list__id=testid)
    get_test = get_object_or_404(Test, id=testid)
    timer = get_test.duration

    expiry_time = get_test.time + datetime.timedelta(minutes=get_test.duration)
    r = expiry_time - timezone.now()
    print(r)
    print(r.seconds)
    if posts.count() is 0:
        return HttpResponse('exam not found!')
    else:
        test = list(posts)
        random.shuffle(test)
        context = {
            'posts': test,
            'no_of_qs':posts.count(),
            'timer': int(r.seconds),
        }
        return render(request,'Test_Designing/t.html',context)
    #return HttpResponse('exam')

@login_required(login_url='result:login')
@user_passes_test(check_student, login_url='/test/error')
def result(request, id):
    test = Test.objects.get(id=id)
    student = Student.objects.get(student=request.user)

    questions = test.questionset.question_set.all()

    correct = 0
    marks = 0
    total_marks = test.total_marks
    for question in questions:
        try:

            ans = request.POST['qs-{}'.format(question.id)]
            if ans == question.answer:
                correct += 1
                marks += question.mark
        except:
            pass

    print(correct)
    print(marks)

    wrong = len(questions) - correct
    StudentResult.objects.create(student=student, test=test, correct_ans=correct, wrong_ans=wrong, marks=marks)

    context = {
        'total_marks':total_marks,
        'marks':marks,
        'correct_ans':correct,
        'wrong_ans':wrong,
    }
    return render(request,'Test_Designing/result.html', context)

#exam-taking views ends here

@login_required(login_url='result:login')
@user_passes_test(check_student, login_url='/test/error')
def list_all_test(request):
    teacher_list = Teacher.objects.filter(followers=request.user.student)
    test_list = []
    for teacher in teacher_list:
        test_list.extend(teacher.test_set.all())

    #test_list = []
    '''
    tl = []
    oneday = datetime.timedelta(days=1)
    for t in list(test_list):

        diff = t.time.date() - datetime.date.today()
        if(diff < oneday ):
            tl.append(t)

        if (t.date.date() > datetime.date.today()):
            tl.append(t)
    #test_list=tl
    '''
    context = {
        'test_list':test_list
    }
    return render(request, 'Test_Designing/quespapers.html', context)

def detail(request, id):
    get_test = get_object_or_404(Test, id=id)
    question_list = get_test.questionset.question_set.all()

    student = Student.objects.get(student=request.user)

    timer = get_test.duration

    expiry_time = get_test.time + datetime.timedelta(minutes=get_test.duration)
    r = expiry_time - timezone.now()

    if (get_test.studentresult_set.filter(student=student).exists()):
        return HttpResponse("You Can't Bruh !")

    if question_list.count() is 0:
        return HttpResponse('exam not found!')

    else:
        test = list(question_list)
        random.shuffle(test)
        context = {
            'posts':test,
            'test':get_test,
            'no_of_qs': question_list.count(),
            'timer': r.seconds,
            'expiry_time': expiry_time
        }

    return render(request, 'Test_Designing/t.html', context)

def testdetail(request, id):
    get_test = get_object_or_404(Test, id=id)
    entry_token = False
    expiry_token= False
    expiry_time = get_test.time + datetime.timedelta(minutes=get_test.duration)
    r =expiry_time - timezone.now()
    if get_test.time < timezone.now():
        entry_token = True
    if expiry_time < timezone.now():
        expiry_token = True

    context = {
        'test':get_test,
        'timer': int(r.seconds),
        'time':get_test.time,
        'marks':get_test.total_marks,
        'entry_token':entry_token,
        'expiry_token':expiry_token,
        'expiry_time':expiry_time,
    }
    return render(request, 'Test_Designing/test_description.html', context)

@login_required()
@user_passes_test(check_teacher, login_url='/test/error')
def my_test(request):
    teacher = get_object_or_404(Teacher, id=request.user.teacher.id)

    test_list = teacher.test_set.all()
    is_done = []

    for test in test_list:
        if test.time < timezone.now():
            is_done.append(True)
        else:
            is_done.append(False)

    test_list_done = zip(test_list, is_done)

    context = {
        'test_list': test_list_done
    }

    return render(request, 'Test_Designing/my_test.html', context)

@login_required()
@user_passes_test(check_teacher, login_url='/test/error')
def edit_test(request, id):
    test = get_object_or_404(Test, id=id)
    question_list = test.questionset.question_set.all()

    context = {
        'q_list': question_list
    }

    # return render(request, 'Test_Designing/edit_test.html', context)

    # return render(request, 'Test_Designing/test_description.html', context)
    return render(request, 'Test_Designing/exam_edit.html', context)

@login_required()
@user_passes_test(check_teacher, login_url='/test/error')
def edit_question(request, id):
    instance = get_object_or_404(Question, id=id)
    print(instance)
    if request.method == 'POST':
        form = QuestionForm(request.POST or None, instance=instance)
        if form.is_valid():
            form.save()

            return redirect('result:dashboard')

    print('no there')
    form = QuestionForm()
    context = {
        'form':form,
        'instance':instance
    }
    return render(request, 'Test_Designing/question_edit.html', context)


#!/usr/bin/env python

from pprint import pprint
from napalm import get_network_driver
import my_devices

def task1b(dev):
    device_type = dev.pop("device_type")
    driver = get_network_driver(device_type)

    device = driver(**dev)
    device.open()
    print(device,"\n")
    facts = device.get_facts()
    pprint(facts)
    print('\n')
    print('The Platform Type is:',device_type)

if __name__ == "__main__":

    #task1b(my_devices.cisco3)

    for d in my_devices.all_devices:
        task1b(d)


from time import time
import pysodium
import msgpack
import logging
import re
from kafkacrypto.utils import str_shim_eq, str_shim_ne, msgpack_default_pack
from kafkacrypto.keys import get_pks, SignPublicKey

class ProcessChainError(ValueError):
  def __init__(self, message, printable):
    super().__init__(message)
    self.printable = printable
  def __str__(self):
    rv = super().__str__()
    if not (self.printable) is None:
      rv += " " + str(self.printable)
    return rv

def key_in_list(wanted, choices):
  # choices is an array of zero or more msgpacked arrays, each of
  # which has the format of a chain entry (see below). This helper
  # function iterates each choice, seeing if the key wanted
  # is present, and returns the match (if any)
  # Right now this has O(n) running time in the length of choices,
  # a future improvement is to make the average running time
  # much faster by building a set of the pk's before calling
  # this function (scaling then is O(logn))
  if wanted is None or choices is None:
    return None
  for c in choices:
    pk = msgpack.unpackb(c,raw=True)
    if wanted == get_pks(pk[2]):
      return c
  return None

def multimatch(wanted, choices):
  # choices is an array of zero or more items, and we return
  # True if wanted is matched by one or more items in choices, and
  # False otherwise. Choices is treated as literal
  # strings except if it starts with "^", in which case it is
  # treated as a regular expression. This matches behaviors
  # of many other libraries, including librdkafka.
  # Wanted is also treated as a literal except if it
  # starts with "^", in which case it is treated as a regular
  # expression. wanted is in choices if:
  #  1. Wanted is a literal, and exactly matches a literal in
  #     choices. [OR]
  #  2. Wanted is a literal, and is matched by a regex in
  #     choices. [OR]
  #  3. Wanted is a regex, and exactly matches a regex in
  #     choices. [OR]
  #  4. Wanted is a regex, and choices as the "match everything"
  #     regex ("^.*$") in it.
  # In particular, this means that regexs in choices are only
  # considered to match a regex wanted if the two (treated as
  # literals) exactly match. This is to ensure that wanted
  # is a strict subset of what choices allows. In principle
  # the regexes could be converted to NFA/DFAs and then checked
  # to ensure a wanted regex is a strict subset of a choices
  # regex, but this is presently unimplemented. It does mean
  # that multimatch is, in some cases, more restrictive than
  # strictly necessary, but this is better than being less
  # restrictive (which is a security hazard).
  if wanted is None:
    return True
  if choices is None:
    return False
  for c in choices:
    if str_shim_eq(c, '^.*$'): # a regex matching all, matches all regexes/literals
      return True
    if len(wanted)<1 or str_shim_ne(wanted[0:1],'^'):
      # wanted is a literal
      if len(c) > 0 and str_shim_eq(c[0:1],'^'):
        r = re.compile(c)
        if r.match(wanted)!=None:
          return True
      elif str_shim_eq(wanted,c):
        return True
    else:
      # wanted is a regex
      if str_shim_eq(wanted,c):
        return True
  # went through all possibilities, did not find it
  return False

def intersect_multimatch(set1, set2):
  if set1==None:
    return set2
  if set2==None:
    return set1
  rv = []
  for w in set2:
    if multimatch(w,set1):
      rv.append(w)
  return rv

def validate_poison(name, value, pk):
  # validate that poison allows the given value for the specified
  # condition (name). It is valid if:
  #   1. Name or value is None. [OR]
  #   2. Name is in poison, not on the exception list,
  #      and value multimatches that condition. [OR]
  #   3. Name is on the exception list, and values matches
  #      as specified for that exception.
  # Otherwise, the condition is invalid and this returns False.
  # Exceptions:
  #   1. Name = "pathlen": valid if pathlen not in poison array,
  #      or if in poison array and value<=that in poison array.
  #
  if name is None or value is None:
    return True
  poison = msgpack.unpackb(pk[1],raw=True)
  for ku in poison:
    if str_shim_eq(ku[0],name):
      if str_shim_ne(name,'pathlen') and multimatch(value,ku[1]):
        return True
      elif str_shim_eq(name,'pathlen') and value<=ku[1]:
        return True
      else:
        return False
  if str_shim_eq(name,'pathlen'):
    return True
  return False

def intersect_certs(c1, c2, same_pk):
  # main logic for determining the minimum allowed values consistent
  # with c1 and c2's constraints. Returns an array with the same
  # structure as a chain entry, with 0,1 set as the intersection of
  # c1 and c2, and values 2:...end set from c2
  # To avoid footguns, we make sure to enforce the following
  # additional conditions:
  # 1. If an item in the chain has key-allowlist or key-denylist, it is
  #    also assumed to imply pathlen = 0, unless explicitly overridden.
  pk = []
  if (c2[0] > 0 and (c2[0]<c1[0] or c1[0] == 0)):
    pk.append(c2[0])
  else:
    pk.append(c1[0])
  poisons = [[-1,msgpack.unpackb(c1[1],raw=True)], [0,msgpack.unpackb(c2[1],raw=True)]]
  if same_pk:
    poisons = [[0,msgpack.unpackb(c1[1],raw=True)], [0,msgpack.unpackb(c2[1],raw=True)]]
  poison_topics = None
  poison_usages = None
  pathlen = None
  for p in poisons:
    pathlen_offset = p[0]
    poison = p[1]
    new_pathlen = None
    for ku in poison:
      if str_shim_eq(ku[0],'topics'):
        poison_topics = intersect_multimatch(poison_topics, ku[1])
      elif str_shim_eq(ku[0],'usages'):
        if (multimatch('key-allowlist',ku[1]) or multimatch('key-denylist',ku[1])) and new_pathlen is None:
          # enforce zero pathlength unless overridden in this poison array
          new_pathlen = 0
        poison_usages = intersect_multimatch(poison_usages, ku[1])
      elif str_shim_eq(ku[0],'pathlen'):
        new_pathlen = ku[1]
      else:
        raise ValueError("Unknown chain signature poison")
    if new_pathlen!=None and (pathlen is None or (new_pathlen+pathlen_offset)<pathlen):
      pathlen = new_pathlen+pathlen_offset
  # Build new poison array
  poison = []
  if poison_topics!=None:
    poison.append(['topics',poison_topics])
  if poison_usages!=None:
    poison.append(['usages',poison_usages])
  if pathlen!=None:
    poison.append(['pathlen',pathlen])
  pk.append(msgpack.packb(poison, default=msgpack_default_pack, use_bin_type=True))
  # Copy entries 2-infinity
  pk = pk + c2[2:]
  return pk

def printable_cert(cert):
  #
  # Convert a certificate to a human-readable format
  #
  rv = []
  try:
    if isinstance(cert[2],(list,tuple)):
      for key in cert[2]:
        rv.append("Key: " + str(key))
    else:
      rv.append("Key: " + str(cert[2]))
    rv.append("Timestamp: " + str(cert[0]))
    rv.append("Poison: " + str(msgpack.unpackb(cert[1],raw=True)))
  except:
    rv.append("Could not parse!")
    rv.append(str(cert))
  return rv

def process_chain(chain, topic=None, usage=None, allowlist=None, denylist=None):
  #
  # chain should be a single msgpack array, with the next item in the array
  # signed by the entity with public key given in the current item. The first
  # item must be signed by a root of trust (which are given in allowlist).
  # Each (signed) item is itself a msgpack array containing:
  # (0) a max_age timestamp (64-bit unsigned unix maximum time signature is valid)
  # (1) a poison array. Sets allowed signature key usages, topics, pathlengths.
  # (2) public key
  # Possibly more items in (3)+, especially common for the final item,
  # but not needed to check the chain.
  #
  # Raises a ValueError if chain does not match topic or usage criteria, or
  # uses a denylisted key, unless there is ultimately a chain between
  # an allowlisted key and the final item with no denylisted keys.
  # The final item might itself be the allowlisted key.
  #
  # Otherwise, returns an array containing two arrays. The first array
  #  contains:
  #  (0) The minimum max_age timestamp
  #  (1) The intersection of allowed topics and usages, in the
  #      poison array (i.e. the net allowed topics and usages)
  #  (2) The public key
  #  And any items in (3)+ from the final item.
  # The second array contains one entry per item in the chain, containing
  # a textual / human readable description (useful for verbose messages) of
  # how the item was interpreted.
  #
  printable = []
  if allowlist is None:
    raise ProcessChainError("No possible roots of trust!", printable)
  last_error = ProcessChainError("No roots of trust found!", printable)
  for rot in allowlist:
    printable = []
    try:
      denylisted = False
      val = [rot] + msgpack.unpackb(chain,raw=True)
      if len(val) < 2:
        # must be validating at least one chain item beyond the item from the allowlist
        raise ValueError("Chain too short!")
      pk = None
      for npk in val:
        if not (pk is None):
          if key_in_list(pk[2],denylist)!=None:
            denylisted = True
            logging.warning("Chain uses denylisted signing key %s.",str(pk[2]))
            # this is not immediately fatal because a subkey might be allowlisted
          elif key_in_list(pk[2],allowlist)!=None:
            # allowlisted subkey overrides denylist
            denylisted = False
            pkn = msgpack.unpackb(key_in_list(pk[2],allowlist),raw=True)
            pkn[2] = get_pks(pkn[2])
            pk = intersect_certs(pk,pkn,True)
          try:
            pkn = pk[2].crypto_sign_open(npk)
            pkn = msgpack.unpackb(pkn,raw=True)
            pkn[2] = get_pks(pkn[2]) # should return a single SignPublicKey except, potentially, at the leaf
            pk = intersect_certs(pk,pkn,False)
          except:
            raise ValueError("Invalid signing!")
        else:
          pk = msgpack.unpackb(npk,raw=True) # root is unsigned
          pk[2] = get_pks(pk[2])
        printable.append(str(printable_cert(pk)))
      # must finally check if leaf key(s) are in allowlist/denylist
      # and remove ones that are
      if isinstance(pk[2],(SignPublicKey,)):
        if key_in_list(pk[2],allowlist)!=None:
          denylisted = False
        if key_in_list(pk[2],denylist)!=None:
          denylisted = True
      else:
        pkn = []
        for pkone in pk[2]:
          if isinstance(pkone,(SignPublicKey,)) and key_in_list(pkone,allowlist):
            # override parent denies
            denylisted = False
          if isinstance(pkone,(SignPublicKey,)) and key_in_list(pkone,denylist):
            # do not use
            pass
          else:
            pkn.append(pkone)
        if len(pkn) < 1:
          denylisted = True
        else:
          pk[2] = pkn
      # make sure our chain doesn't have breaking denylisted keys
      if denylisted:
        raise ValueError("Chain uses denylisted public key")
      # ensure composite chain is valid
      if (pk[0]<time() and pk[0]!=0):
        raise ValueError("Expired Chain!")
      if not validate_poison('topics',topic,pk):
        raise ValueError("No matching topic in allowed intersection set.")
      if not validate_poison('usages',usage,pk):
        raise ValueError("No matching usage in allowed intersection set.")
      if not validate_poison('pathlen',0,pk):
        raise ValueError("Exceeded allowed pathlen.")
      return [pk,printable]
    except ValueError as e:
      printable.append(str(e))
      last_error = ProcessChainError("Error during Validation:", printable)
  # We allow a key to self-sign itself to be denylisted. This enables any private
  # key to denylist itself
  try:
    chain = msgpack.unpackb(chain,raw=True)
    if len(chain) == 2:
      pk = msgpack.unpackb(chain[0],raw=True)
      pk0 = get_pks(pk[2])
      pkn = pk0.crypto_sign_open(chain[1])
      pkn = msgpack.unpackb(pkn,raw=True)
      pkn[2] = get_pks(pkn[2])
      pk = intersect_certs(pk,pkn,False)
      pk[2] = get_pks(pk[2])
      if pk0 == pk[2] and multimatch(usage, ['key-denylist']) and validate_poison('usages','key-denylist',pk) and validate_poison('pathlen',0,pk):
        return [pk,[str(printable_cert(pk))]]
  except:
    pass
  raise last_error


def greet(name = 'Saheed', msg='Good Bye'):
    print('Hello', name)
greet()
greet('Oladiipo')
greet(name='Python')
#print(name, msg)
print('######################')

def greet(name = 'Saheed', msg='Good Bye'):
    #print('Hello', name)
    print('Hello', name, msg)
greet()
greet('Oladiipo')
greet(name='Python')
greet(name='Fatimah')
print('____________________')
greet(name='Hawwa', msg='Good Morning')
greet('Peter', 'Good afternoon')
greet('Aisha', msg='Bye')
greet(msg='Good Evening', name='Muhammad')
#print(name, msg)


import docker
from docker .errors import NotFound, APIError
# system
import sys, os
import pathlib
import logging
from datetime import datetime
# MultiThreading
from threading import Thread
# Own
from arq_decorators.service_decorator import enableFunction
from arq_server.services.CoreService import Configuration
from arq_server.base.ArqErrors import ArqError
from arq_server.base.Metadata import Metadata

class DockerTools(object):
    __isEnabled:bool = True
    __logger: logging.Logger
    __config: Configuration

    def __init__(self, core, *args, **kwargs):
        self.__init_services(core)
        self.__logger.debug("Módulo DockerTools isEnabled:%s",str(self.__isEnabled))
        self.__init_client()
        self.__docker_conf_alias = self.__config.getProperty("groups", "docker")
        self.__dockerLogsPath = self.__config.getProperty("docker","path.docker.logs",confKey=self.__docker_conf_alias)

    def runContainer(
        self, image, name:str, auto_remove:bool=False, detach:bool=False,
        command:str=None, ports:dict=None, volumes:dict=None
        ):
        """
        Arranca un contenedor a partir de la imagen dada como argumento.
        El nombre es obligatorio para gestionar internamente los contenedores activos
        """
        conf = {
            "name":name,
            "auto_remove":auto_remove,
            "detach":detach
            }

        if command:
            conf['command'] = command
        if ports:
            conf['ports'] = ports
        if ports:
            conf['volumes'] = volumes

        self.__logger.debug("generando contenedor '%s' a partir de la imagen '%s'",name,image)
        self.__logger.debug("configuración recogida para generar el contenedor: %s",conf)

        self.__client.containers.run(
            image,
            **conf
            )

        self.__logger.debug("Contenedor '%s' generado",name)
        c = self.__client.containers.get(name)
        streamLogsThread = Thread(target = self.__streamContainerLogs, args = (name,c, ))
        streamLogsThread.start()

    def stopContainer(self,name) -> bool:
        isStoped:bool=False
        try:
            container = self.__client.containers.get(name)
            container.stop()
            self.__logger.debug("el contenedor %s fué detenido",name)
            isStoped=True
        except NotFound as not_found_e:
            raise ArqError(not_found_e.response)
        finally:
            return isStoped

    def removeContainer(self, name) -> bool:
        isRemoved:bool = False
        try:
            container = self.__client.containers.get(name)
            if container.status == "running":
                self.stopContainer(name)
                container = self.__client.containers.get(name)
            container.remove()
            isRemoved=True
            self.__logger.debug("el contenedor %s fué eliminado", name)
        except NotFound as not_found_e:
            self.__logger.error("El contenedor %s no se encuentra o ya ha sido eliminado", name)
        finally:
            return isRemoved

    def __streamContainerLogs(self, name, container):
        dateInfo = datetime.now().strftime("%Y_%m_%d-%H_%M_%S")
        logPath = "{}\\{}__{}.log".format(self.__dockerLogsPath,name,dateInfo)
        f=open(logPath,"wb")
        self.__logger.debug("Generando un stream de logs para el contenedor %s en la ruta %s",name,logPath)
        try:
            for l in container.logs(stream=True):
                f.write(l)
        except Exception as e:
            self.__logger.error("Error durante el stream a fichero de los logs del contenedor %s",name)
            print(e)

        finally:
            f.close()

    @enableFunction(__isEnabled,className='DockerTools')
    def __init_client(self):
        self.__client = docker.from_env()
        self.__logger.info("API herramientas Docker cargada correctamente")

    def __init_services(self, core) -> None:
        # Servicio de logging
        self.__core = core
        self.__logger = core.logger_service().arqLogger()
        self.__config = core.config_service()


def foo(L, p, r):
    if (p==r):
            return L[p]
    if(r+1== p):
            return 1

    else:
        mid = (p+r)//2
        leftmid = (p +mid)//2
        rightmid = (mid+ r)//2

        first = foo(L, p, leftmid)
        second = foo(L, leftmid+1, mid)
        third = foo(L, mid + 1, rightmid)
        fourth = foo(L, rightmid+1, r)

    return first * second * third * fourth

print(foo([3,4,5,7,7,5,3,2,9,1], 0, 9))


from time import time, sleep
from typing import Any

def benchmark(method: Any, critical_time: float):
    """
    This is function for time execution calc
    :param method: Class method
    :param critical_time: critical time execution value in sec
    :return: func
    """
    def wrapper(*args, **kwargs):
        time_start = time()
        res = method(*args, **kwargs)
        if time() - time_start >= critical_time:
            print(f'WARNING! {method} slow!! Time is: {time() - time_start} sec, critical_time = {critical_time}')
        return res

    return wrapper

def decor_time_critical(critical_time: float):
    """
    External func decor for receiving critical timeout
    :param critical_time: critical time execution value in sec
    :return: internal func decorator
    """
    def decor_time_critical_without_time(cls):
        class DecorClass:
            """New Class that changed input class"""
            def __init__(self, *args, **kwargs):
                self._obj = cls(*args, **kwargs)

            def __getattribute__(self, item):
                try:
                    is_my_attribute = super().__getattribute__(item)
                except AttributeError:
                    pass
                else:
                    return is_my_attribute

                val_attr = self._obj.__getattribute__(item)

                if callable(val_attr):
                    return benchmark(val_attr, critical_time)
                else:
                    return val_attr

        return DecorClass

    return decor_time_critical_without_time

@decor_time_critical(0.5)
class Test:
    def method_1(self):
        print('slow method start')
        sleep(1)
        print('slow method finish')

    def method_2(self):
        print('fast method start')
        sleep(0.1)
        print('fast method finish')

t = Test()

t.method_1()
t.method_2()

# slow method start
# slow method finish
# WARNING! method_1 slow. Time = ??? sec.
# fast method start
# fast method finish


class Solution:
    def fizzBuzz(self, n):
        """
        :type n: int
        :rtype: List[str]
        """
        arr = []
        for i in range(1,n+1):
            if i%3 == 0 and i%5 ==0:
                arr.append("FizzBuzz")
                continue
            if i%3 == 0:
                arr.append("Fizz")
                continue
            if i%5 == 0:
                arr.append("Buzz")
                continue
            arr.append(str(i))
        return arr
    ##key is continue as it will just jump to next iteration