import argparse
import string

import utils
import filerepair
import logger

def ParseCommandLineArguments():
	rtn = utils.DefaultOpts()

	parser = argparse.ArgumentParser(description='construct a "RAID" file for the given input-file')
	parser.add_argument( '-C', nargs=1, type=str, help='read opts file' )
	parser.add_argument( '-L', nargs=1, type=str, help='send output to log file' )
	parser.add_argument( '-b', nargs=1, type=str, help='set the block size (default='+
		str(rtn['block_size'])+')' )
	parser.add_argument( '-c', nargs=1, type=str, help='set the cksum algorithm (default='+
		rtn['cksum_algo']+')' )
	parser.add_argument( '-p', nargs=1, type=str, help='set the number of parity disks (default='+
		str(rtn['num_parity_disks'])+')' )
	parser.add_argument( '-i', action='count', help='use interleaved parity' )
	parser.add_argument( '-r', action='count', help='use Reed-Solomon parity' )
	parser.add_argument( '-X', action='count', help='use hypercube-raid system' )
	parser.add_argument( '-v', action='count', help='verbose output' )
	parser.add_argument( '-V', action='count', help='really verbose output' )
	parser.add_argument( 'command', nargs=1, help='command to execute (create, verify, repair)' )
	parser.add_argument( 'filelist', nargs='+', help='file(s) to work with' )

	#
	# parse the command-line arguments
	params = vars( parser.parse_args() )

	# set a new opts file
	if( params['C'] != None ):
		#rtn['opts_file'] = params['C'][0]
		# parse the opts file
		rtn = utils.read_config_file( params['C'][0], rtn )

	# set the number of stripes
	if( params['p'] != None ):
		rtn['num_parity_disks'] = int( params['p'][0] )

	if( params['b'] != None ):
		rtn['block_size'] = utils.convert_from_kmgt( params['b'][0] )

	# XOR/RAID-4/5 parity or Reed-Solomon
	if( params['i'] != None ):
		rtn['parity_type'] = 'i'
	elif( params['r'] != None ):
		rtn['parity_type'] = 'r'
	elif( params['X'] != None ):
		rtn['parity_type'] = 'x'

	# set cksum algorithm (if needed)
	if( params['c'] != None ):
		rtn['cksum_algo'] = string.upper(params['c'][0])

	# make the code a bit more readable
	if( params['v'] != None ):
		rtn['verbose'] = params['v']
	if( params['V'] != None ):
		rtn['verbose'] += 10*params['V']

	# log to file?
	if( params['L'] != None ):
		rtn['log_file'] = params['L'][0]

	# pass the command through
	rtn['command'] = params['command'][0]

	# pass any filenames through
	rtn['file_list'] = params['filelist']

	return rtn

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

def main():
	# parse the command-line arguments (starts with DefaultOpts() )
	opts = ParseCommandLineArguments()

	# open the log (to either stdout or file)
	logger.openLog( opts )

	# parse the opts file
	#if( opts['opts_file'] != None ):
	#	opts = read_config_file( opts['opts_file'], opts )

	err = -200
	command = opts['command']

	if( command == 'create' ):
		# create cksum-data for a file
		infile = opts['file_list'][0]
		chkfile = utils.calc_chk_filename( infile, opts )
		err = filerepair.create_from_file( infile, chkfile, opts )

	elif( command == 'verify' ):
		# to verify a file, we need a cksum-file to compare to
		infile = opts['file_list'][0]
		if( len(opts['file_list']) >= 2 ):
			chkfile = opts['file_list'][1]
		else:
			chkfile = utils.calc_chk_filename( infile, opts )
		err = filerepair.verify_file( infile, chkfile, opts )

	elif( command == 'repair' ):
		# to repair a file, we need a cksum-file to compare to
		infile = opts['file_list'][0]
		if( len(opts['file_list']) >= 2 ):
			chkfile = opts['file_list'][1]
		else:
			chkfile = utils.calc_chk_filename( infile, opts )
		if( len(opts['file_list']) >= 3 ):
			repfile = opts['file_list'][2]
		else:
			repfile = utils.calc_rep_filename( infile, opts )
		err = filerepair.repair_file( infile, chkfile, repfile, opts )

	elif( command == 'createall' ):
		# create cksum-data for all files in dir (per opts file)
		utils.go_nice( opts )
		inpath = opts['file_list'][0]
		def cmd_create( infile, _opts ):
			chkfile = utils.calc_chk_filename( infile, _opts )
			err = filerepair.create_from_file( infile, chkfile, _opts )
			return err

		err = utils.walk_directory_tree( inpath, opts, cmd_create )

	elif( command == 'verifyall' ):
		# verify all files in a dir (per opts file)
		utils.go_nice( opts )
		inpath = opts['file_list'][0]
		def cmd_verify( infile, _opts ):
			chkfile = utils.calc_chk_filename( infile, _opts )
			err = filerepair.verify_file( infile, chkfile, _opts )
			return err

		err = utils.walk_directory_tree( inpath, opts, cmd_verify )

	elif( command == 'repairall' ):
		# repair all files in a dir (per opts file)
		utils.go_nice( opts )
		inpath = opts['file_list'][0]
		def cmd_repair( infile, _opts ):
			chkfile = utils.calc_chk_filename( infile, _opts )
			repfile = utils.calc_rep_filename( infile, _opts )
			err = filerepair.repair_file( infile, chkfile, repfile, _opts )
			return err

		err = utils.walk_directory_tree( inpath, opts, cmd_repair )

	elif( command == 'updateall' ):
		# create or verify all files in a dir (per opts file)
		utils.go_nice( opts )
		inpath = opts['file_list'][0]
		def cmd_update( infile, _opts ):
			chkfile = utils.calc_chk_filename( infile, _opts )
			# if cksum file exists, then verify it
			if( file_exists(chkfile) ):
				err = filerepair.verify_file( infile, chkfile, _opts )
			# else create it
			else:
				err = filerepair.create_from_file( infile, chkfile, _opts )
			return err

		err = utils.walk_directory_tree( inpath, opts, cmd_update )

	else:
		# shouldn't be able to get here!
		print( "* Error: unknown command" )
		err = -100

	# close/clean-up the log file
	logger.closeLog()

	exit( err )

if __name__ == '__main__':
	main()


import ldap3
changes_done = "test2"
changes_done = "test3"
SERVER='80.0.0.108'
BASEDN="OU=Delhi AISGlass,OU=AIS Users,DC=asahiindia,DC=com"
USER="test3@asahiindia.com"
CURREENTPWD="P@ssword@1234"
NEWPWD="P@ssword@12345679"

SEARCHFILTER='(&(userPrincipalName='+USER+')(objectClass=person))'
print(SEARCHFILTER)
USER_DN=""
USER_CN=""

ldap_server = ldap3.Server(SERVER, get_info=ldap3.ALL)
conn = ldap3.Connection(ldap_server, USER, CURREENTPWD, auto_bind=True)
conn.start_tls()
print(f"conn is = {conn}")
conn.search(search_base = BASEDN,
         search_filter = SEARCHFILTER,
         search_scope = ldap3.SUBTREE,
         attributes = ['cn', 'givenName', 'userPrincipalName'],
         paged_size = 5)

print(conn.entries)
for entry in conn.response:
    print(f"entry is {entry}")
    if entry["dn"] and entry["attributes"]:
        if entry.get("attributes").get("userPrincipalName"):
            if entry.get("attributes").get("userPrincipalName") == USER:
                USER_DN=entry.get("dn")
                USER_CN=entry.get("attributes").get("cn")

print("Found user:", USER_CN)

if USER_DN:
    print(USER_DN)
    print(ldap3.extend.microsoft.modifyPassword.ad_modify_password(conn, USER_DN, NEWPWD, CURREENTPWD,  controls=None))
else:
    print("User DN is missing!")


import networkx as nx
import torch
from torch_geometric.data import Batch, Data

def increasing_mask(
    batch_size: int, seq_len: int, start_with_zero: bool = False
) -> torch.Tensor:
    """
    Return an increasing mask. Useful for tests. For example:
    batch_size = 3, seq_len = 2, start_with_zero = False
    [
        [1, 0],
        [1, 1],
        [1, 1],
    ]
    batch_size = 3, seq_len = 2, start_with_zero = True
    [
        [0, 0],
        [1, 0],
        [1, 1],
    ]
    """
    data: list[list[int]] = []
    for i in range(batch_size):
        if i < seq_len:
            if start_with_zero:
                data.append([1] * i + [0] * (seq_len - i))
            else:
                data.append([1] * (i + 1) + [0] * (seq_len - i - 1))
        else:
            data.append([1] * seq_len)
    return torch.tensor(data, dtype=torch.float)

class EqualityDiGraph(nx.DiGraph):
    def __eq__(self, o: object) -> bool:
        if not isinstance(o, EqualityDiGraph):
            return False

        return self.nodes.data() == o.nodes.data() and list(self.edges.data()) == list(
            o.edges.data()
        )

class EqualityData(Data):
    def __eq__(self, o: object) -> bool:
        if not isinstance(o, EqualityData):
            return False

        return (
            self.x.equal(o.x)
            and self.node_label_mask.equal(o.node_label_mask)
            and self.node_last_update.equal(o.node_last_update)
            and self.edge_index.equal(o.edge_index)
            and self.edge_attr.equal(o.edge_attr)
            and self.edge_label_mask.equal(o.edge_label_mask)
            and self.edge_last_update.equal(o.edge_last_update)
        )

class EqualityBatch(Batch):
    def __eq__(self, o: object) -> bool:
        if not isinstance(o, EqualityBatch):
            return False

        return (
            self.batch.equal(o.batch)
            and self.x.equal(o.x)
            and self.node_label_mask.equal(o.node_label_mask)
            and self.node_last_update.equal(o.node_last_update)
            and self.edge_index.equal(o.edge_index)
            and self.edge_attr.equal(o.edge_attr)
            and self.edge_label_mask.equal(o.edge_label_mask)
            and self.edge_last_update.equal(o.edge_last_update)
        )


#!/usr/bin/env python
"""
This is a straightforward Python implementation of a generative adversarial network.
The code is derived from the O'Reilly interactive tutorial on GANs
(https://www.oreilly.com/learning/generative-adversarial-networks-for-beginners).

The tutorial's code trades efficiency for clarity in explaining how GANs function;
this script refactors a few things to improve performance, especially on GPU machines.
In particular, it uses a TensorFlow operation to generate random z values and pass them
to the generator; this way, more computations are contained entirely within the
TensorFlow graph.

A version of this model with explanatory notes is also available on GitHub
at https://github.com/jonbruner/generative-adversarial-networks.

This script requires TensorFlow and its dependencies in order to run. Please see
the readme for guidance on installing TensorFlow.

This script won't print summary statistics in the terminal during training;
track progress and see sample images in TensorBoard.
"""

import tensorflow as tf
import datetime
import matplotlib.pyplot as plt
import numpy as np

# Load MNIST data
from tensorflow.examples.tutorials.mnist import input_data
#读取数据集
mnist = input_data.read_data_sets("MNIST_data/")

# Define the discriminator network
#具有两个卷积层和两个全连接层，特征为5x5
def discriminator(images, reuse_variables=None):
    #遍历各层数据
    with tf.variable_scope(tf.get_variable_scope(), reuse=reuse_variables) as scope:
        # First convolutional and pool layers
        # This finds 32 different 5 x 5 pixel features
        #截断正态分布初始化权值
        d_w1 = tf.get_variable('d_w1', [5, 5, 1, 32], initializer=tf.truncated_normal_initializer(stddev=0.02))
        #初始化偏置
        d_b1 = tf.get_variable('d_b1', [32], initializer=tf.constant_initializer(0))
        #标准库中的卷积神经网络
        d1 = tf.nn.conv2d(input=images, filter=d_w1, strides=[1, 1, 1, 1], padding='SAME')
        #增加偏置
        d1 = d1 + d_b1
        #激活函数
        d1 = tf.nn.relu(d1)
        #池化来处理特征
        d1 = tf.nn.avg_pool(d1, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

        # Second convolutional and pool layers
        # This finds 64 different 5 x 5 pixel features
        # 截断正态分布初始化权值
        d_w2 = tf.get_variable('d_w2', [5, 5, 32, 64], initializer=tf.truncated_normal_initializer(stddev=0.02))
        # 初始化偏置
        d_b2 = tf.get_variable('d_b2', [64], initializer=tf.constant_initializer(0))
        # 标准库中的卷积神经网络
        d2 = tf.nn.conv2d(input=d1, filter=d_w2, strides=[1, 1, 1, 1], padding='SAME')
        # 增加偏置
        d2 = d2 + d_b2
        # 激活函数
        d2 = tf.nn.relu(d2)
        # 池化来处理特征
        d2 = tf.nn.avg_pool(d2, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding='SAME')

        # First fully connected layer
        # 截断正态分布初始化权值
        d_w3 = tf.get_variable('d_w3', [7 * 7 * 64, 1024], initializer=tf.truncated_normal_initializer(stddev=0.02))
        # 初始化偏置
        d_b3 = tf.get_variable('d_b3', [1024], initializer=tf.constant_initializer(0))
        #整合数据
        d3 = tf.reshape(d2, [-1, 7 * 7 * 64])
        #矩阵相乘获得函数值
        d3 = tf.matmul(d3, d_w3)
        #增加偏置
        d3 = d3 + d_b3
        #激活函数
        d3 = tf.nn.relu(d3)

        # Second fully connected layer
        #截断正态分布初始化权值
        d_w4 = tf.get_variable('d_w4', [1024, 1], initializer=tf.truncated_normal_initializer(stddev=0.02))
        #初始化偏置
        d_b4 = tf.get_variable('d_b4', [1], initializer=tf.constant_initializer(0))
        #与权重相乘，增加偏置
        d4 = tf.matmul(d3, d_w4) + d_b4
        # d4 contains unscaled values
        #返回一个标量，可认为是置信值
        return d4

# Define the generator network
#定义生成网络
def generator(z, batch_size, z_dim):
    #输入为56x56大小，设置权重
    g_w1 = tf.get_variable('g_w1', [z_dim, 3136], dtype=tf.float32, initializer=tf.truncated_normal_initializer(stddev=0.02))
    #设置偏置，大小同上
    g_b1 = tf.get_variable('g_b1', [3136], initializer=tf.truncated_normal_initializer(stddev=0.02))
    #乘上权重+偏置
    g1 = tf.matmul(z, g_w1) + g_b1
    #向量转化为数组
    g1 = tf.reshape(g1, [-1, 56, 56, 1])
    #用于归一化，加快运算速度
    g1 = tf.contrib.layers.batch_norm(g1, epsilon=1e-5, scope='bn1')
    #激活函数
    g1 = tf.nn.relu(g1)

    # Generate 50 features
    #第二层网络权重
    g_w2 = tf.get_variable('g_w2', [3, 3, 1, z_dim/2], dtype=tf.float32, initializer=tf.truncated_normal_initializer(stddev=0.02))
    #第二层网络偏置
    g_b2 = tf.get_variable('g_b2', [z_dim/2], initializer=tf.truncated_normal_initializer(stddev=0.02))
    #引用标准网络
    g2 = tf.nn.conv2d(g1, g_w2, strides=[1, 2, 2, 1], padding='SAME')
    #加偏置
    g2 = g2 + g_b2
    #用于归一化，加快运算速度
    g2 = tf.contrib.layers.batch_norm(g2, epsilon=1e-5, scope='bn2')
    #激活函数
    g2 = tf.nn.relu(g2)
    #调整大小
    g2 = tf.image.resize_images(g2, [56, 56])

    # Generate 25 features
    #第三层网络权重
    g_w3 = tf.get_variable('g_w3', [3, 3, z_dim/2, z_dim/4], dtype=tf.float32, initializer=tf.truncated_normal_initializer(stddev=0.02))
    #第三层网络偏置
    g_b3 = tf.get_variable('g_b3', [z_dim/4], initializer=tf.truncated_normal_initializer(stddev=0.02))
    #引用标准网络
    g3 = tf.nn.conv2d(g2, g_w3, strides=[1, 2, 2, 1], padding='SAME')
    #加偏置
    g3 = g3 + g_b3
    # 用于归一化，加快运算速度
    g3 = tf.contrib.layers.batch_norm(g3, epsilon=1e-5, scope='bn3')
    #激活函数
    g3 = tf.nn.relu(g3)
    #调整大小
    g3 = tf.image.resize_images(g3, [56, 56])

    # Final convolution with one output channel
    #第四层权重
    g_w4 = tf.get_variable('g_w4', [1, 1, z_dim/4, 1], dtype=tf.float32, initializer=tf.truncated_normal_initializer(stddev=0.02))
    #第四层偏置
    g_b4 = tf.get_variable('g_b4', [1], initializer=tf.truncated_normal_initializer(stddev=0.02))
    #标准网络
    g4 = tf.nn.conv2d(g3, g_w4, strides=[1, 2, 2, 1], padding='SAME')
    #加偏置
    g4 = g4 + g_b4
    #激活函数使得图像变为灰度图像
    g4 = tf.sigmoid(g4)
    # Dimensions of g4: batch_size x 28 x 28 x 1
    #返回28x28图像数据
    return g4

#批个数定义
z_dimensions = 100

#设定维度大小
z_placeholder = tf.placeholder(tf.float32, [None, z_dimensions])

#生成器输出
generated_image_output = generator(z_placeholder, 1, z_dimensions)
#生成噪音
z_batch = np.random.normal(0, 1, [1, z_dimensions])

with tf.Session() as sess:
    #初始化变量
    sess.run(tf.global_variables_initializer())
    #生成图片
    generated_image = sess.run(generated_image_output,
                                feed_dict={z_placeholder: z_batch})
    #生成的向量重塑
    generated_image = generated_image.reshape([28, 28])
    plt.imshow(generated_image, cmap='Greys')

#设定张量图
tf.reset_default_graph()
#设定包大小
batch_size = 50
#生成器噪音
z_placeholder = tf.placeholder(tf.float32, [None, z_dimensions], name='z_placeholder')
# z_placeholder is for feeding input noise to the generator
#判别器输入
x_placeholder = tf.placeholder(tf.float32, shape = [None,28,28,1], name='x_placeholder')
# x_placeholder is for feeding input images to the discriminator
#存储生成器图片
Gz = generator(z_placeholder, batch_size, z_dimensions)
# Gz holds the generated images
#存储判别器的输出
Dx = discriminator(x_placeholder)
# Dx will hold discriminator prediction probabilities
# for the real MNIST images
#存储生成器图片的判别后的概率
Dg = discriminator(Gz, reuse_variables=True)
# Dg will hold discriminator prediction probabilities for generated images

#判别器真实图片输出与1的交叉熵
d_loss_real = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits = Dx, labels = tf.ones_like(Dx)))
#判别器生成图片输出与0的交叉熵
d_loss_fake = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits = Dg, labels = tf.zeros_like(Dg)))

g_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits = Dg, labels = tf.ones_like(Dg)))

#存储训练变量
tvars = tf.trainable_variables()
#判别器权重、偏置
d_vars = [var for var in tvars if 'd_' in var.name]
#生成器权重、偏置
g_vars = [var for var in tvars if 'g_' in var.name]
#输出判别器name
print([v.name for v in d_vars])
#输出生成器name
print([v.name for v in g_vars])

# Train the discriminator
#训练判别器（生成图片）
d_trainer_fake = tf.train.AdamOptimizer(0.0003).minimize(d_loss_fake, var_list=d_vars)
#训练判别器（真实图片）
d_trainer_real = tf.train.AdamOptimizer(0.0003).minimize(d_loss_real, var_list=d_vars)

# Train the generator
#训练生成器
g_trainer = tf.train.AdamOptimizer(0.0001).minimize(g_loss, var_list=g_vars)

# From this point forward, reuse variables
#获取变量
tf.get_variable_scope().reuse_variables()

#生成器损失
tf.summary.scalar('Generator_loss', g_loss)
#判别器对真实图片的损失
tf.summary.scalar('Discriminator_loss_real', d_loss_real)
#判别器对生成图片的损失
tf.summary.scalar('Discriminator_loss_fake', d_loss_fake)
#获取生成图
images_for_tensorboard = generator(z_placeholder, batch_size, z_dimensions)
#图像写入summary便于查看
tf.summary.image('Generated_images', images_for_tensorboard, 5)
#管理summary
merged = tf.summary.merge_all()
#图像名设定
logdir = "tensorboard/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S") + "/"
#结果写入tensorboard
writer = tf.summary.FileWriter(logdir, sess.graph)

#'''
#设定会话
sess = tf.Session()
#启动会话
sess.run(tf.global_variables_initializer())

# Pre-train discriminator
#预训练，便于设定权重和偏置
for i in range(300):
    #初始化zbatch用于预训练
    z_batch = np.random.normal(0, 1, size=[batch_size, z_dimensions])
    #真实图片的遍历
    real_image_batch = mnist.train.next_batch(batch_size)[0].reshape([batch_size, 28, 28, 1])
    #获取真实图片损失和生成图片损失
    _, __, dLossReal, dLossFake = sess.run([d_trainer_real, d_trainer_fake, d_loss_real, d_loss_fake],
                                           {x_placeholder: real_image_batch, z_placeholder: z_batch})
    #每100批进行一次输出
    if(i % 100 == 0):
        print("dLossReal:", dLossReal, "dLossFake:", dLossFake)

# Train generator and discriminator together
#同时进行生成器和判别器的训练
for i in range(100000):
    #提取真实图片批
    real_image_batch = mnist.train.next_batch(batch_size)[0].reshape([batch_size, 28, 28, 1])
    #初始化zbatch用于预训练
    z_batch = np.random.normal(0, 1, size=[batch_size, z_dimensions])

    # Train discriminator on both real and fake images
    #获取真实图片损失和生成图片损失
    _, __, dLossReal, dLossFake = sess.run([d_trainer_real, d_trainer_fake, d_loss_real, d_loss_fake],
                                           {x_placeholder: real_image_batch, z_placeholder: z_batch})

    # Train generator
    #初始化zbatch用于预训练
    z_batch = np.random.normal(0, 1, size=[batch_size, z_dimensions])
    #启动会话训练
    _ = sess.run(g_trainer, feed_dict={z_placeholder: z_batch})
    #每10次更新一次
    if i % 10 == 0:
        # Update TensorBoard with summary statistics
        #zbatch初始化
        z_batch = np.random.normal(0, 1, size=[batch_size, z_dimensions])
        #赋值summary便于管理
        summary = sess.run(merged, {z_placeholder: z_batch, x_placeholder: real_image_batch})
        #写入summary
        writer.add_summary(summary, i)
    #每100次输出一次
    if i % 100 == 0:
        # Every 100 iterations, show a generated image
        #输出遍历次数、时间
        print("Iteration:", i, "at", datetime.datetime.now())
        #初始化zbatch用于预训练
        z_batch = np.random.normal(0, 1, size=[1, z_dimensions])
        #生成图像
        generated_images = generator(z_placeholder, 1, z_dimensions)
        #启动会话
        images = sess.run(generated_images, {z_placeholder: z_batch})
        #图像组织
        plt.imshow(images[0].reshape([28, 28]), cmap='Greys')
        #图像显示
        plt.show()

        # Show discriminator's estimate
        #组织图像
        im = images[0].reshape([1, 28, 28, 1])
        #图像判别
        result = discriminator(x_placeholder)
        #估计结果
        estimate = sess.run(result, {x_placeholder: im})
        #输出结果
        print("Estimate:", estimate)
#'''
#调用存储器
saver = tf.train.Saver()
#开始会话
with tf.Session() as sess:
    #获取存储的模型
    saver.restore(sess, 'pretrained-model/pretrained_gan.ckpt')
    #设定批大小
    z_batch = np.random.normal(0, 1, size=[10, z_dimensions])
    #存储模型
    z_placeholder = tf.placeholder(tf.float32, [None, z_dimensions], name='z_placeholder')
    #运用已有模型生成图像
    generated_images = generator(z_placeholder, 10, z_dimensions)
    #启动会话
    images = sess.run(generated_images, {z_placeholder: z_batch})
    #遍历输出图像
    for i in range(10):
        #提取灰度图像
        plt.imshow(images[i].reshape([28, 28]), cmap='Greys')
        #图像显示
        plt.show()


import Chemins
from Utils.UTILS_Traduction import _
import wx
import six
from Ctrl import CTRL_Bouton_image
from PIL import Image
import FonctionsPerso

def pil2wx(image):
    """Convert a PIL image to wx image format"""
    imagewx=wx.EmptyImage(image.size[0], image.size[1])
    imagewx.SetData(image.tobytes('raw', 'RGB'))
    return imagewx

def load_image(fn):
    """Read a file into PIL Image object. Return the image and file size"""
    buf = six.BytesIO()
    f=open(fn,"rb")
    while 1:
        rdbuf=f.read(8192)
        if not rdbuf: break
        buf.write(rdbuf)
    f.close()
    buf.seek(0)
    image=Image.open(buf).convert("RGB")
    return image,len(buf.getvalue())

def save_image_buf(image,q=90):
    """Save a PIL Image into a byte buffer as a JPEG with the given quality.
    Return the buffer and file size.
    """
    buf = six.BytesIO()
    image.save(buf,format='JPEG',quality=q)
    buf.seek(0)
    return buf,len(buf.getvalue())

def wxtopil(image):
    """Convert wx.Image to PIL Image."""
    pil = Image.new('RGB', (image.GetWidth(), image.GetHeight()))
    pil.frombytes(image.GetData())
    return pil

class ImgBox(wx.Window):
    def __init__(self, parent, id=-1, image=None):
        wx.Window.__init__(self, parent, -1, wx.DefaultPosition, wx.DefaultSize, wx.NO_FULL_REPAINT_ON_RESIZE |wx.SUNKEN_BORDER)

        self.fichierImageSource = image
        self.InitImage()

        # Binds
        wx.EVT_PAINT(self, self.evt_paint)
        wx.EVT_SIZE(self, self.evt_size)

    def InitImage(self):
        # Chargement de l'image source
        self.sourcePIL, self.origsize = load_image(self.fichierImageSource)
        # Transforme l'image PIL en wx.Image
        self.source = pil2wx(self.sourcePIL)
        # Initialise les valeurs
        self.posxPhoto = None
        self.posyPhoto = None

        self.largeurDC = None
        self.hauteurDC = None

        self.tailleCadre = 384

    def ReinitImage(self):
        self.InitImage()
        self.evt_size(None)

    def Draw(self,dc):
        """Draw the image bitmap and decoration on the buffered DC"""
        dc.SetBackground(wx.BLACK_BRUSH)
        dc.Clear()
        dc.SetFont(wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL, False, 'Arial'))

        # Dessin de la photo
        largeurImg, hauteurImg = self.bmp.GetSize()
        largeurDC, hauteurDC = self.GetClientSizeTuple()
        dc.DrawBitmap(self.bmp, (largeurDC / 2.0)  - (largeurImg / 2.0), (hauteurDC / 2.0) - (hauteurImg / 2.0), 0)

    def evt_paint(self, event):
        """Paint event handler with double buffering"""
        dc = wx.BufferedPaintDC(self, self._Buffer)

    def evt_size(self,event):
        """ OnSize """
        self.ResizePhoto()
        largeurDC, hauteurDC = self.GetClientSizeTuple()
        # Redessine toute l'image
        self._Buffer = wx.EmptyBitmap(largeurDC, hauteurDC)
        self.UpdateDrawing()

    def ResizePhoto(self):
        """ Redimensionne la photo"""
        largeurImg, hauteurImg = self.source.GetSize()
        self.ratio = self.GetParent().slider_ratio.GetValue() / 100.0
        source = self.source.Scale(largeurImg * self.ratio, hauteurImg * self.ratio)
        self.bmp=wx.BitmapFromImage(source)

    def UpdateDrawing(self):
        """Create the device context and draw the window contents"""
        dc = wx.BufferedDC(wx.ClientDC(self), self._Buffer)
        dc.BeginDrawing()
        self.Draw(dc)
        dc.EndDrawing()

    def SetRatio(self):
        """ ratio """
        self.ResizePhoto()
        self.UpdateDrawing()

    def Rotation(self, VersDroite=True):
        """ Rotation de la photo """
        # Rotation
        self.source = self.source.Rotate90(VersDroite)
        # Réduction de l'image
        largeurImg, hauteurImg = self.source.GetSize()
        source = self.source.Scale(largeurImg * self.ratio, hauteurImg * self.ratio)
        self.bmp=wx.BitmapFromImage(source)
        # MAJ de l'affichage de la photo
        self.UpdateDrawing()

    def SaveImage(self):
        # Paramètres de sauvegarde
        jpeg_quality = 90

        # Création du nom de fichier
        nomFichier = "Photos/"
        codeIDfichier = self.RecupIDfichier()
        IDpersonne = self.GetGrandParent().IDpersonne
        nomFichier += codeIDfichier + str(IDpersonne) + ".jpg"

        # Récupération de l'image dans le cadre de sélection
        tailleImg = self.selection.GetSize()
        imgTemp = self.selection.GetSubBitmap( (0, 0, tailleImg[0], tailleImg[1]) )
        imgFinale = wxtopil(imgTemp.ConvertToImage())

        # Sauvegarde
        try:
            buf, bytes=save_image_buf(imgFinale, jpeg_quality)
            ok=1
            if ok:
                save_image_file(nomFichier,buf)
                print("Saved image to %s (%.f kB)" % (nomFichier, bytes/1024))
        except:
                print("Failed to save image!")
                return None
        return nomFichier

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

class MyDialog(wx.Dialog):
    def __init__(self, parent, image=None, titre=_(u"Editeur photo")):
        wx.Dialog.__init__(self, parent, -1, title=titre, name="frm_photo", size=(700, 600))

        # Widgets
        self.imgbox = ImgBox(self,-1, image=image)

        self.staticBox_rotation = wx.StaticBox(self, -1, _(u"Rotation"))
        self.bouton_rotation_gauche = wx.BitmapButton(self, -1, wx.Bitmap(Chemins.GetStaticPath("Images/22x22/RotationGauche.png"), wx.BITMAP_TYPE_PNG))
        self.bouton_rotation_droite = wx.BitmapButton(self, -1, wx.Bitmap(Chemins.GetStaticPath("Images/22x22/RotationDroite.png"), wx.BITMAP_TYPE_PNG))

        self.staticBox_ratio = wx.StaticBox(self, -1, _(u"Taille de l'image"))
        self.slider_ratio = wx.Slider(self, -1,  100, 1, 200, size=(-1, -1), style=wx.SL_HORIZONTAL)
        self.img_loupe_plus = wx.StaticBitmap(self, -1, wx.Bitmap(Chemins.GetStaticPath("Images/22x22/zoomPlus.png"), wx.BITMAP_TYPE_ANY))
        self.img_loupe_moins = wx.StaticBitmap(self, -1, wx.Bitmap(Chemins.GetStaticPath("Images/22x22/zoomMoins.png"), wx.BITMAP_TYPE_ANY))

        self.staticBox_reinit = wx.StaticBox(self, -1, _(u"Réinitialisation"))
        self.bouton_reinit = wx.BitmapButton(self, -1, wx.Bitmap(Chemins.GetStaticPath("Images/22x22/Photo.png"), wx.BITMAP_TYPE_ANY), size=(70, -1))

        # Boutons
        self.bouton_aide = CTRL_Bouton_image.CTRL(self, texte=_(u"Aide"), cheminImage=Chemins.GetStaticPath("Images/32x32/Aide.png"))
        self.bouton_ok = CTRL_Bouton_image.CTRL(self, texte=_(u"Ok"), cheminImage=Chemins.GetStaticPath("Images/32x32/Valider.png"))
        self.bouton_annuler = CTRL_Bouton_image.CTRL(self, id=wx.ID_CANCEL, texte=_(u"Annuler"), cheminImage=Chemins.GetStaticPath("Images/32x32/Annuler.png"))

        self.__set_properties()
        self.__do_layout()

        self.Bind(wx.EVT_BUTTON, self.OnBoutonRotationGauche, self.bouton_rotation_gauche)
        self.Bind(wx.EVT_BUTTON, self.OnBoutonRotationDroite, self.bouton_rotation_droite)
        self.Bind(wx.EVT_SCROLL, self.OnScrollSlider, self.slider_ratio)
        self.Bind(wx.EVT_BUTTON, self.OnBoutonReinit, self.bouton_reinit)
        self.Bind(wx.EVT_BUTTON, self.OnBoutonAide, self.bouton_aide)
        self.Bind(wx.EVT_BUTTON, self.OnBoutonOk, self.bouton_ok)

    def __set_properties(self):
        self.SetTitle(_(u"Editeur de photo"))
        if 'phoenix' in wx.PlatformInfo:
            _icon = wx.Icon()
        else :
            _icon = wx.EmptyIcon()
        _icon.CopyFromBitmap(wx.Bitmap(Chemins.GetStaticPath("Images/16x16/Logo.png"), wx.BITMAP_TYPE_ANY))
        self.SetIcon(_icon)
        self.bouton_aide.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour obtenir de l'aide")))
        self.bouton_ok.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour valider l'image")))
        self.bouton_annuler.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour annuler")))

        self.bouton_rotation_gauche.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour effectuer une rotation de 90°\n dans le sens inverse des aiguilles d'une montre")))
        self.bouton_rotation_droite.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour effectuer une rotation de 90°\n dans le sens des aiguilles d'une montre")))
        self.slider_ratio.SetToolTip(wx.ToolTip(_(u"Ajustez avec cette fonction ratio\nla taille de la photo")))
        self.bouton_reinit.SetToolTip(wx.ToolTip(_(u"Cliquez ici pour réinitialiser la position\net la taille de la photo initiale")))

    def __do_layout(self):
        sizer_base = wx.BoxSizer(wx.VERTICAL)
        grid_sizer_base = wx.FlexGridSizer(rows=3, cols=1, vgap=0, hgap=0)

        # DC
        grid_sizer_base.Add(self.imgbox, 1, wx.LEFT|wx.TOP|wx.RIGHT|wx.EXPAND, 10)

        # Panneau de contrôle
        sizer_commandes = wx.FlexGridSizer(rows=1, cols=5, vgap=5, hgap=5)

        # Rotation
        staticBox_rotation = wx.StaticBoxSizer(self.staticBox_rotation, wx.HORIZONTAL)
        staticBox_rotation.Add(self.bouton_rotation_gauche, 0, wx.ALL, 2)
        staticBox_rotation.Add(self.bouton_rotation_droite, 0, wx.ALL, 2)
        sizer_commandes.Add(staticBox_rotation, 1, wx.EXPAND, 0)

        # ratio
        staticBox_ratio = wx.StaticBoxSizer(self.staticBox_ratio, wx.HORIZONTAL)
        staticBox_ratio.Add(self.img_loupe_moins, 0, wx.ALL, 2)
        staticBox_ratio.Add(self.slider_ratio, 1, wx.EXPAND | wx.ALL, 2)
        staticBox_ratio.Add(self.img_loupe_plus, 0, wx.ALL, 2)
        sizer_commandes.Add(staticBox_ratio, 1, wx.EXPAND, 0)

        # Reinit
        staticBox_reinit = wx.StaticBoxSizer(self.staticBox_reinit, wx.HORIZONTAL)
        staticBox_reinit.Add(self.bouton_reinit, 0, wx.ALL, 2)
        sizer_commandes.Add(staticBox_reinit, 1, wx.EXPAND, 0)

        grid_sizer_base.Add(sizer_commandes, 1, wx.EXPAND | wx.ALL, 10)

        sizer_commandes.AddGrowableRow(0)
        sizer_commandes.AddGrowableCol(1)

        # Boutons
        grid_sizer_boutons = wx.FlexGridSizer(rows=1, cols=4, vgap=10, hgap=10)
        grid_sizer_boutons.Add(self.bouton_aide, 0, 0, 0)
        grid_sizer_boutons.Add((20, 20), 0, wx.EXPAND, 0)
        grid_sizer_boutons.Add(self.bouton_ok, 0, 0, 0)
        grid_sizer_boutons.Add(self.bouton_annuler, 0, 0, 0)
        grid_sizer_boutons.AddGrowableCol(1)

        grid_sizer_base.AddGrowableCol(0)
        grid_sizer_base.AddGrowableRow(0)
        grid_sizer_base.Add(grid_sizer_boutons, 1, wx.LEFT|wx.RIGHT|wx.BOTTOM|wx.EXPAND, 10)
        self.SetSizer(grid_sizer_base)
        sizer_base.Add(self, 1, wx.EXPAND, 0)
        self.Layout()
        self.CentreOnScreen()

    def Fermer(self):
        self.EndModal(wx.ID_CANCEL)

    def GetBmp(self):
        return self.imgbox.bmp

    def OnBoutonAide(self, event):
        from Utils import UTILS_Aide
        UTILS_Aide.Aide("")

    def OnBoutonOk(self, event):
        # Ferme la boîte de dialogue
        self.EndModal(wx.ID_OK)

    def OnBoutonRotationGauche(self, event):
        self.imgbox.Rotation(False)

    def OnBoutonRotationDroite(self, event):
        self.imgbox.Rotation(True)

    def OnScrollSlider(self, event):
        """ On Slider """
        self.imgbox.SetRatio()

    def OnBoutonReinit(self, event):
        self.slider_ratio.SetValue(100)
        self.imgbox.ReinitImage()

if __name__ == "__main__":
    app = wx.App(0)
    #wx.InitAllImageHandlers()
    frm = MyDialog(None, image="img.jpg")
    frm.ShowModal()
    app.MainLoop()


import asyncio
import concurrent.futures
import glob
import json
import logging
import os
import shutil
import sys
import tempfile
import uuid
from asyncio.exceptions import CancelledError
from datetime import datetime
from functools import partial
from pprint import pprint
from typing import Callable, Dict, List, Optional, Union

import ansible_runner
import dpath.util
import janus
import yaml

if os.environ.get("RULES_ENGINE", "durable_rules") == "drools":
    from drools.vendor import lang
else:
    from durable import lang

from .collection import find_playbook, has_playbook, split_collection_name
from .conf import settings
from .exception import ShutdownException
from .util import get_horizontal_rule

logger = logging.getLogger()

async def none(
    event_log,
    inventory: Dict,
    hosts: List,
    variables: Dict,
    facts: Dict,
    ruleset: str,
):
    await event_log.put(
        dict(
            type="Action",
            action="noop",
            activation_id=settings.identifier,
            run_at=str(datetime.utcnow()),
        )
    )

async def debug(event_log, **kwargs):
    print(get_horizontal_rule("="))
    print("context:")
    pprint(lang.c.__dict__)
    print(get_horizontal_rule("="))
    print("facts:")
    pprint(lang.get_facts(kwargs["ruleset"]))
    print(get_horizontal_rule("="))
    print("kwargs:")
    pprint(kwargs)
    print(get_horizontal_rule("="))
    sys.stdout.flush()
    await event_log.put(
        dict(
            type="Action",
            action="debug",
            playbook_name=kwargs.get("name"),
            activation_id=settings.identifier,
            run_at=str(datetime.utcnow()),
        )
    )

async def print_event(
    event_log,
    inventory: Dict,
    hosts: List,
    variables: Dict,
    facts: Dict,
    ruleset: str,
    name: Optional[str] = None,
    var_root: Union[str, Dict, None] = None,
    pretty: Optional[str] = None,
):
    print_fn: Callable = print
    if pretty:
        print_fn = pprint

    if var_root:
        update_variables(variables, var_root)

    var_name = "event"
    if "events" in variables:
        var_name = "events"

    print_fn(variables[var_name])
    sys.stdout.flush()
    await event_log.put(
        dict(
            type="Action",
            action="print_event",
            activation_id=settings.identifier,
            playbook_name=name,
            run_at=str(datetime.utcnow()),
        )
    )

async def assert_fact(
    event_log,
    inventory: Dict,
    hosts: List,
    variables: Dict,
    facts: Dict,
    ruleset: str,
    fact: Dict,
    name: Optional[str] = None,
):
    logger.debug(f"assert_fact {ruleset} {fact}")
    lang.assert_fact(ruleset, fact)
    await event_log.put(
        dict(
            type="Action",
            action="assert_fact",
            activation_id=settings.identifier,
            playbook_name=name,
            run_at=str(datetime.utcnow()),
        )
    )

async def retract_fact(
    event_log,
    inventory: Dict,
    hosts: List,
    variables: Dict,
    facts: Dict,
    ruleset: str,
    fact: Dict,
    name: Optional[str] = None,
):
    lang.retract_fact(ruleset, fact)
    await event_log.put(
        dict(
            type="Action",
            action="retract_fact",
            activation_id=settings.identifier,
            playbook_name=name,
            run_at=str(datetime.utcnow()),
        )
    )

async def post_event(
    event_log,
    inventory: Dict,
    hosts: List,
    variables: Dict,
    facts: Dict,
    ruleset: str,
    event: Dict,
):
    lang.post(ruleset, event)

    await event_log.put(
        dict(
            type="Action",
            action="post_event",
            activation_id=settings.identifier,
            run_at=str(datetime.utcnow()),
        )
    )

async def run_playbook(
    event_log,
    inventory: Dict,
    hosts: List,
    variables: Dict,
    facts: Dict,
    ruleset: str,
    name: str,
    assert_facts: Optional[bool] = None,
    post_events: Optional[bool] = None,
    verbosity: int = 0,
    var_root: Union[str, Dict, None] = None,
    copy_files: Optional[bool] = False,
    json_mode: Optional[bool] = False,
    retries: Optional[int] = 0,
    retry: Optional[bool] = False,
    delay: Optional[int] = 0,
    **kwargs,
):

    logger.info(f"running Ansible playbook: {name}")
    temp, playbook_name, job_id = await pre_process_runner(
        event_log,
        inventory,
        variables,
        facts,
        ruleset,
        name,
        "run_playbook",
        var_root,
        copy_files,
        True,
        **kwargs,
    )
    logger.info("Calling Ansible runner")

    if retry:
        retries = max(retries, 1)
    for i in range(retries + 1):
        if i > 0 and delay > 0:
            await asyncio.sleep(delay)

        run_at = str(datetime.utcnow())
        await call_runner(
            event_log,
            job_id,
            temp,
            dict(playbook=playbook_name),
            hosts,
            verbosity,
            json_mode,
        )
        if get_status(temp) != "failed":
            break

    return await post_process_runner(
        event_log,
        temp,
        ruleset,
        settings.identifier,
        name,
        "run_playbook",
        job_id,
        run_at,
        assert_facts,
        post_events,
    )

async def run_module(
    event_log,
    inventory: Dict,
    hosts: List,
    variables: Dict,
    facts: Dict,
    ruleset: str,
    name: str,
    assert_facts: Optional[bool] = None,
    post_events: Optional[bool] = None,
    verbosity: int = 0,
    var_root: Union[str, Dict, None] = None,
    copy_files: Optional[bool] = False,
    json_mode: Optional[bool] = False,
    module_args: Union[Dict, None] = None,
    retries: Optional[int] = 0,
    retry: Optional[bool] = False,
    delay: Optional[int] = 0,
    **kwargs,
):

    temp, module_name, job_id = await pre_process_runner(
        event_log,
        inventory,
        variables,
        facts,
        ruleset,
        name,
        "run_module",
        var_root,
        copy_files,
        False,
        **kwargs,
    )
    logger.info("Calling Ansible runner")
    module_args_str = ""
    if module_args:
        for k, v in module_args.items():
            if len(module_args_str) > 0:
                module_args_str += " "
            module_args_str += f'{k}="{v}"'

    if retry:
        retries = max(retries, 1)
    for i in range(retries + 1):
        if i > 0 and delay > 0:
            await asyncio.sleep(delay)

        run_at = str(datetime.utcnow())
        await call_runner(
            event_log,
            job_id,
            temp,
            dict(
                module=module_name,
                host_pattern=",".join(hosts),
                module_args=module_args_str,
            ),
            hosts,
            verbosity,
            json_mode,
        )
        if get_status(temp) != "failed":
            break

    return await post_process_runner(
        event_log,
        temp,
        ruleset,
        settings.identifier,
        name,
        "run_module",
        job_id,
        run_at,
        assert_facts,
        post_events,
    )

async def call_runner(
    event_log,
    job_id: str,
    private_data_dir: str,
    runner_args: Dict,
    hosts: List,
    verbosity: int = 0,
    json_mode: Optional[bool] = False,
):

    host_limit = ",".join(hosts)

    loop = asyncio.get_running_loop()

    queue = janus.Queue()

    # The event_callback is called from the ansible-runner thread
    # It needs a thread-safe synchronous queue.
    # Janus provides a sync queue connected to an async queue
    # Here we push the event into the sync side of janus
    def event_callback(event, *args, **kwargs):
        event["job_id"] = job_id
        event["ansible_events_id"] = settings.identifier
        logger.debug("event_callback")
        queue.sync_q.put(dict(type="AnsibleEvent", event=event))

    # Here we read the async side and push it into the event queue
    # which is also async.
    # We do this until cancelled at the end of the ansible runner call.
    # We might need to drain the queue here before ending.
    async def read_queue():
        try:
            while True:
                val = await queue.async_q.get()
                event_data = val.get("event", {})
                val["run_at"] = event_data.get("created")
                await event_log.put(val)
        except CancelledError:
            pass

    tasks = []

    tasks.append(asyncio.create_task(read_queue()))

    with concurrent.futures.ThreadPoolExecutor(max_workers=1) as task_pool:
        await loop.run_in_executor(
            task_pool,
            partial(
                ansible_runner.run,
                private_data_dir=private_data_dir,
                limit=host_limit,
                verbosity=verbosity,
                event_handler=event_callback,
                json_mode=json_mode,
                **runner_args,
            ),
        )

    # Cancel the queue reading task
    for task in tasks:
        task.cancel()
    await asyncio.gather(*tasks)

async def pre_process_runner(
    event_log,
    inventory: Dict,
    variables: Dict,
    facts: Dict,
    ruleset: str,
    name: str,
    action: str,
    var_root: Union[str, Dict, None] = None,
    copy_files: Optional[bool] = False,
    check_files: Optional[bool] = True,
    **kwargs,
):

    private_data_dir = tempfile.mkdtemp(prefix=action)
    logger.debug(f"private data dir {private_data_dir}")
    logger.debug(f"variables {variables}")
    logger.debug(f"facts {facts}")

    variables["facts"] = facts
    for k, v in kwargs.items():
        variables[k] = v

    if var_root:
        update_variables(variables, var_root)

    playbook_name = name
    if True:
        os.mkdir(os.path.join(private_data_dir, "env"))
        with open(
            os.path.join(private_data_dir, "env", "extravars"), "w"
        ) as f:
            f.write(yaml.dump(variables))
        os.mkdir(os.path.join(private_data_dir, "inventory"))
        with open(
            os.path.join(private_data_dir, "inventory", "hosts"), "w"
        ) as f:
            f.write(yaml.dump(inventory))
        os.mkdir(os.path.join(private_data_dir, "project"))

    if check_files:
        if os.path.exists(name):
            playbook_name = os.path.basename(name)
            shutil.copy(
                name, os.path.join(private_data_dir, "project", playbook_name)
            )
            if copy_files:
                shutil.copytree(
                    os.path.dirname(os.path.abspath(name)),
                    os.path.join(private_data_dir, "project"),
                    dirs_exist_ok=True,
                )
        elif has_playbook(*split_collection_name(name)):
            playbook_name = name
            shutil.copy(
                find_playbook(*split_collection_name(name)),
                os.path.join(private_data_dir, "project", name),
            )
        else:
            logger.error(
                f"Could not find a playbook for {name} from {os.getcwd()}"
            )

    job_id = str(uuid.uuid4())

    await event_log.put(
        dict(type="Job", job_id=job_id, ansible_events_id=settings.identifier)
    )
    return (private_data_dir, playbook_name, job_id)

async def post_process_runner(
    event_log,
    private_data_dir: str,
    ruleset: str,
    activation_id: str,
    name: str,
    action: str,
    job_id: str,
    run_at: str,
    assert_facts: Optional[bool] = None,
    post_events: Optional[bool] = None,
):

    for rc_file in glob.glob(
        os.path.join(private_data_dir, "artifacts", "*", "rc")
    ):
        with open(rc_file, "r") as f:
            rc = int(f.read())

    status = get_status(private_data_dir)

    result = dict(
        type="Action",
        action=action,
        activation_id=activation_id,
        playbook_name=name,
        job_id=job_id,
        ruleset=ruleset,
        rc=rc,
        status=status,
        run_at=run_at,
    )
    await event_log.put(result)

    if assert_facts or post_events:
        logger.debug("assert_facts")
        for host_facts in glob.glob(
            os.path.join(private_data_dir, "artifacts", "*", "fact_cache", "*")
        ):
            with open(host_facts) as f:
                fact = json.loads(f.read())
            logger.debug(f"fact {fact}")
            if assert_facts:
                lang.assert_fact(ruleset, fact)
            if post_events:
                lang.post(ruleset, fact)

    return result

async def shutdown(
    event_log,
    inventory: Dict,
    hosts: List,
    variables: Dict,
    facts: Dict,
    ruleset: str,
):
    await event_log.put(
        dict(
            type="Action",
            action="shutdown",
            activation_id=settings.identifier,
            run_at=str(datetime.utcnow()),
        )
    )
    raise ShutdownException()

actions: Dict[str, Callable] = dict(
    none=none,
    debug=debug,
    print_event=print_event,
    assert_fact=assert_fact,
    retract_fact=retract_fact,
    post_event=post_event,
    run_playbook=run_playbook,
    run_module=run_module,
    shutdown=shutdown,
)

def update_variables(variables: Dict, var_root: Union[str, Dict]):
    var_roots = {var_root: var_root} if isinstance(var_root, str) else var_root
    if "event" in variables:
        for key, _new_key in var_roots.items():
            new_value = dpath.util.get(
                variables["event"], key, separator=".", default=None
            )
            if new_value:
                variables["event"] = new_value
                break
    elif "events" in variables:
        for _k, v in variables["events"].items():
            for old_key, new_key in var_roots.items():
                new_value = dpath.util.get(
                    v, old_key, separator=".", default=None
                )
                if new_value:
                    variables["events"][new_key] = new_value
                    break

def get_status(private_data_dir: str):
    status_files = glob.glob(
        os.path.join(private_data_dir, "artifacts", "*", "status")
    )
    status_files.sort(key=os.path.getmtime, reverse=True)
    with open(status_files[0], "r") as f:
        status = f.read()
    return status


import fillpdf
from fillpdf import fillpdfs

f = fillpdfs.get_form_fields('input.pdf')

data_dict = {
    'Address1 Text Box': '500 West Main Street',
    'Driving License Check Box': 'Yes',
    'Language 1 Check Box': 'Off',
}

fillpdfs.write_fillable_pdf('blank.pdf', 'new.pdf', data_dict)

print(f)


from reportlab.pdfgen import canvas
from django.http import HttpResponseRedirect
from django.template import loader, RequestContext
from shutil import copyfile
from django.shortcuts import get_object_or_404, render
from django.views.decorators.csrf import csrf_exempt

from .models import WagonDrawing

@csrf_exempt
def index(request):
	if request.method == 'POST':
		cid = request.POST.get('cid')
		wagtemp = WagonDrawing.objects.filter(iid=cid)
		oktemp = WagonDrawing.objects.filter(iid=cid)
		for e in wagtemp:
			wagnumber = e.wagon_number
		for f in oktemp:
			okdate = f.ok_date
		return HttpResponseRedirect('/commission/' + str(cid) + '/')
		#return HttpResponseRedirect('/commission/wagon/' + str(okdate) + '/' + str(wagnumber) + '/')
	else:
		ok_date_list = WagonDrawing.objects.values('ok_date').distinct().order_by('ok_date')
		context = {'ok_date_list': ok_date_list}
		return render(request, 'commission/index.html', context)

def choosewagon(request, okdate):
	wagond_list = WagonDrawing.objects.filter(ok_date=okdate).values('wagon_number').distinct().order_by('wagon_number')
	context = {'wagond_list': wagond_list, 'okdate' : okdate}
	return render(request, 'commission/wagonlist.html', context)

def wagon(request, wagnumber, okdate):
	draw_list = WagonDrawing.objects.filter(ok_date=okdate, wagon_number=wagnumber).order_by('-link')
	context = {'draw_list': draw_list, 'okdate' : okdate}
	return render(request, 'commission/drawlist.html', context)

def product(request, pid):
	draw_list = WagonDrawing.objects.filter(iid = pid).order_by('-link')
	for drawing in draw_list:
		okdate = str(drawing.ok_date)
	context = {'draw_list': draw_list, 'okdate': okdate}
	return render(request, 'commission/productdrawing.html', context)

#def index(request):
	#ok_date_list = WagonDrawing.objects.values('ok_date').distinct()
	#context = {'ok_date_list': ok_date_list}
	#return render(request, 'commission/index.html', context)


from flask import Flask, request, jsonify
from dotenv import load_dotenv
from flask_cors import CORS
from src.external.repositories.mongodb.productsrepository import MongoProductsRepository
from src.usecases.createproduct import CreateProductUseCase
from src.usecases.updateproduct import UpdateProductUseCase, ChangeType
from markupsafe import escape

load_dotenv()

app = Flask(__name__)
cors = CORS(app, resources={r"/api/*": { "origins": "*" }})

@app.route("/api/product", methods=["POST"])
def create_product():
  name = request.json["name"]
  price = request.json["price"]
  mongo_products_repository = MongoProductsRepository()
  create_product_use_case = CreateProductUseCase(mongo_products_repository)
  try:
    product = create_product_use_case.execute(name, price)
    return {
      "id": product.id,
      "name": product.name,
      "price": product.price,
      "active": product.active
    }, 201
  except Exception as error:
    return {
      "error": str(error)
    }, 400

@app.route("/api/product", methods=["GET"])
def get_all_products():
  try:
    page = request.args.get("page", default = 1, type = int)
    limit = request.args.get("limit", default = 10, type = int)
    mongo_products_repository = MongoProductsRepository()
    products = list(map(
      lambda product: {
        "id": product["id"],
        "name": product["name"],
        "price": product["price"],
        "active": product["active"]
      },
      mongo_products_repository.get_all(limit, page)
    ))
    total_items = mongo_products_repository.count()
    return jsonify({
      "products": products,
      "total_items": total_items
    }), 201
  except Exception as error:
    return {
      "error": str(error)
    }, 400

@app.route("/api/product/<product_id>", methods=["PATCH"])
def update_product(product_id):
  try:
    mongo_products_repository = MongoProductsRepository()
    update_product_use_case = UpdateProductUseCase(mongo_products_repository)
    if "name" in request.json:
      update_product_use_case.execute(
        escape(product_id),
        ChangeType.NAME,
        request.json["name"]
      )
    if "price" in request.json:
      update_product_use_case.execute(
        escape(product_id),
        ChangeType.PRICE,
        request.json["price"]
      )
    return jsonify(mongo_products_repository.find_by_id(escape(product_id))), 201
  except Exception as error:
    return {
      "error": str(error)
    }, 400

@app.route("/api/product/<product_id>/disable", methods=["PATCH"])
def disable_product(product_id):
  try:
    mongo_products_repository = MongoProductsRepository()
    update_product_use_case = UpdateProductUseCase(mongo_products_repository)
    update_product_use_case.execute(
      escape(product_id),
      ChangeType.ACTIVE_STATUS,
      False
    )
    return jsonify(mongo_products_repository.find_by_id(escape(product_id))), 201
  except Exception as error:
    return {
      "error": str(error)
    }, 400

@app.route("/api/product/<product_id>/active", methods=["PATCH"])
def active_product(product_id):
  try:
    mongo_products_repository = MongoProductsRepository()
    update_product_use_case = UpdateProductUseCase(mongo_products_repository)
    update_product_use_case.execute(
      escape(product_id),
      ChangeType.ACTIVE_STATUS,
      True
    )
    return jsonify(mongo_products_repository.find_by_id(escape(product_id))), 201
  except Exception as error:
    return {
      "error": str(error)
    }, 400


import pygame
import random
import math
import sys

pygame.init()

screen = pygame.display.set_mode((800, 600))

running = True

backgroundImage = pygame.image.load('backgr.jpg')
pygame.display.set_caption('Spaceship')

playerImage = pygame.image.load('player.png')
player_x = 370
player_y = 480
player_dx = 0

pygame.display.set_icon(playerImage)

enemyImage = pygame.image.load('enemy.png')
enemy_x = random.randint(0, 736)
enemy_y = random.randint(50, 150)
enemy_dx = 4
enemy_dy = 1

bulletImage = pygame.image.load('bullet.png')
bullet_x = 0
bullet_y = 480
bullet_dx = 0
bullet_dy = 10
bullet_m = 'ready'

score = 0

def player(x, y):
    screen.blit(playerImage, (x, y))

def enemy(x, y):
    screen.blit(enemyImage, (x, y))

def fire_bullet(x, y):
    global bullet_m
    bullet_m = 'fire'
    screen.blit(bulletImage, (x + 16, y + 10))

def collision(enemy_x, enemy_y, bullet_x, bullet_y):
    dis = math.sqrt(math.pow(enemy_x - bullet_x,2) + math.pow(enemy_y - bullet_y,2))
    if dis < 27:
        return True
    else:
        return False

while running:
    screen.fill((0, 0, 0))
    screen.blit(backgroundImage, (0,0))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    pressed = pygame.key.get_pressed()
    if pressed[pygame.K_LEFT]:
        player_x -= 5
    if pressed[pygame.K_RIGHT]:
        player_x += 5
    if pressed[pygame.K_SPACE]:
        if bullet_m is 'ready':
            bullet_x = player_x
            fire_bullet(player_x, bullet_y)

    if event.type == pygame.KEYUP:
        if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
            player_dx = 0

    player_x += player_dx
    if player_x <= 0:
        player_x = 0
    elif player_x >= 736:
        player_x = 736

    enemy_x += enemy_dx
    if enemy_x <= 0:
        enemy_dx = 4
        enemy_y += enemy_dx
    elif enemy_x >= 736:
        enemy_dx = -4
        enemy_y -= enemy_dx

    if bullet_y <=0:
        bullet_y = 480
        bullet_m = 'ready'

    if bullet_m is 'fire':
        fire_bullet(bullet_x, bullet_y)
        bullet_y -= bullet_dy

    coll = collision(enemy_x, enemy_y, bullet_x, bullet_y)
    if coll:
        bullet_y = 480
        bullet_m = 'ready'
        score += 1
        print(score)
        enemy_x = random.randint(0, 735)
        enemy_y = random.randint(50, 150)

    if score == 3:
        sys.exit()

    player(player_x, player_y)
    enemy(enemy_x, enemy_y)
    pygame.display.update()

    pygame.display.flip()


# Approach
# Read the text file with all the vector data
# Use plotting library to dislpay the map
# Plot tutorial found on: https://stackoverflow.com/questions/12265234/how-to-plot-2d-math-vectors-with-matplotlib

import numpy as np
import matplotlib.pyplot as plt
import ast

path_to_txt_file = 'map_vectors.txt'
f = open(path_to_txt_file,'r')
lines = f.read().splitlines()
vectors = []
for i in lines:
    vectors.append(ast.literal_eval(i))
soa = np.array(vectors)
X,Y,U,V = zip(*soa)
plt.figure()
ax = plt.gca()
ax.quiver(X,Y,U,V,angles='xy',scale_units='xy',scale=1)
ax.set_xlim([-5,10])
ax.set_ylim([-5,10])
plt.draw()
plt.show()


from pytube import YouTube
import whisper
import os

def audio_to_text(link):

    try:
        # link='https://youtu.be/Wn9iALMyS7c?si=q0LYZBrR9mSbj2b7'
        video = YouTube(link)
        # video.set_filename('audio_file')
        stream = video.streams.filter(only_audio=True).first()
        stream.download(filename=f"audiofile.mp3")
        print("audio file generated")

        model = whisper.load_model("tiny")

        audio = whisper.load_audio("audiofile.mp3")
        audio = whisper.pad_or_trim(audio)
        mel = whisper.log_mel_spectrogram(audio).to(model.device)
        _, probs = model.detect_language(mel)
        print(f"Detected language: {max(probs, key=probs.get)}")

        if (max(probs, key=probs.get) !='en'):
            print("Can't perform ASR on other languages.")
            return("Can't perform ASR on other languages.")
        else:
            print("performing..")
            result = model.transcribe("audiofile.mp3")
            # time.sleep(2)
            # result = model.transcribe("audiofile.mp3",fp16=False)
            final_data=""
            with open("transcript.txt","w") as f:
                final_data+=result["text"]
                f.write(result["text"])

            # os.remove('./audiofile.mp3')
            print("done")
            return('1')

    except:
        print("Couldn't find audio")
        return("Couldn't find audio")

    # except:
    #     print("ASR error")
    #     return("ASR error")

    # return("hieie")

    # text = open("transcript.txt",'w')
    # text.write(clean_data)
    # text.close()

    # return("hiiiiiiiiii")

# audio_to_text()


import argparse
import csv
from collections import OrderedDict
from datetime import date, datetime
from jira import JIRA
from prettytable import PrettyTable

JIRA_LOCATIONS = OrderedDict([
    ('JBOSS', 'https://issues.jboss.org'),
    ('HIBERNATE', 'https://hibernate.atlassian.net'),
    ('APACHE', 'https://issues.apache.org/jira')
])
FIELDS = ['project', 'summary', 'key', 'status', 'reporter', 'assignee', 'updated', 'comment']

_first_csv_domain = True

def check_negative_int(value):
    try:
        ret_value = int(value)
    except ValueError:
        raise argparse.ArgumentTypeError("Invalid input '{}', --jira-limit parameter must be a valid integer")

    if ret_value < 1:
        raise argparse.ArgumentTypeError("invalid input '{}', --jira-limit parameter must be > 0".format(value))
    return ret_value

def valid_date(string):
    try:
        return datetime.strptime(string, "%Y-%m-%d").date()
    except ValueError:
        raise argparse.ArgumentTypeError("Not a valid date: '{0}'.".format(string))

def create_ascii_table(headers):
    table = PrettyTable(headers)
    table.align = 'l'
    table.max_width = 12
    table.max_width['Title'] = table.max_width['Link'] = 60
    table.align['#User Comments'] = 'r'
    return table

def print_ascii_row(table, row_data, empty_row=None):
    if table is not None:
        table.add_row(row_data)
        if empty_row is not None:
            table.add_row(empty_row)

def write_csv_row(csv_writer, row_data):
    if csv_writer is not None:  # Only write headers if csv writer exists
        csv_writer.writerow(row_data)

def write_csv_headers(domain, headers, **kwargs):
    global _first_csv_domain
    if not _first_csv_domain:
        write_csv_row(kwargs.get('csv_writer'), [])
    write_csv_row(kwargs.get('csv_writer'), [domain + ' issues'])
    write_csv_row(kwargs.get('csv_writer'), headers)
    _first_csv_domain = False

def output_issue(domain, username, issue, table=None, **kwargs):
    user_roles = list(kwargs.get('user_roles', []))
    if issue.fields.reporter.name == username:
        user_roles.append('Reporter')

    link = domain + "/browse/" + issue.key
    updated_time = issue.fields.updated[:10].replace('-', '/')
    comments = [comment for comment in issue.fields.comment.comments if comment.author.name == username]

    row_content = [issue.key, issue.fields.project.name, issue.fields.summary, ','.join(user_roles),
                   issue.fields.status.name, len(comments), link, updated_time]

    # Add to ascii table if enabled
    print_ascii_row(table, row_content, [''] * 8)

    # Write to csv file
    write_csv_row(kwargs.get('csv_writer'), row_content)

def process_issues(domain, username, issues, **kwargs):
    headers = ['ID', 'Project', 'Title', 'Role', 'Status', '#Comments', 'Link', 'Updated On']
    table = create_ascii_table(headers) if kwargs.get('ascii') else None
    write_csv_headers(domain, headers, **kwargs)

    for issue in issues:
        output_issue(domain, username, issue, table=table, **kwargs)

    if table is not None:
        print(table)

def search_jira_domains(domains, username, **kwargs):
    search_field = ','.join(FIELDS)
    search_str = "(assignee = {0} OR reporter = {0})" \
                 "AND (updated >= '{1}' OR created >= '{1}')" \
                 "AND (updated < '{2}' OR created < '{2}')" \
                 "ORDER BY updated {3}".format(username, kwargs.get('start_date', date(1990, 1, 1)),
                                               kwargs.get('end_date', date.today()), kwargs.get('order', 'ASC'))

    for key, domain in domains.items():
        jira = JIRA(domain)
        issues = jira.search_issues(search_str, fields=search_field, maxResults=kwargs.get('jira_limit', 50))

        if issues:
            if kwargs.get('ascii'):
                print("{0} issues".format(key))

            process_issues(domain, username, issues, **kwargs)

def get_program_args():
    parser = argparse.ArgumentParser(description='Returns JIRA issues associated with a given user')
    parser.add_argument('usernames', nargs='+', help='At least one JIRA username must be specified.')

    parser.add_argument('-s', '--startDate', dest='start_date', type=valid_date, default=date(1990, 1, 1),
                        metavar='YYYY-MM-DD', help="The date from which JIRAs are returned.")

    parser.add_argument('-e', '--endDate', dest='end_date', type=valid_date, default=date.today(), metavar='YYYY-MM-DD',
                        help="The date of the most recent JIRA to be returned.")

    parser.add_argument('-d', '--domains', nargs='+', choices=JIRA_LOCATIONS.keys(), default=JIRA_LOCATIONS,
                        help="A list of the JIRA keys associated with the domain(s) that should be searched.")

    parser.add_argument('-jl', '--jira-limit', dest='jira_limit', type=check_negative_int, default=50,
                        help="The maximum number of JIRA issues that will be returned for each domain.")

    parser.add_argument('--lifo', dest='order', action='store_const', const='DESC', default='ASC',
                        help="JIRA issues are output from the most recently updated issue.")

    parser.add_argument('--no-ascii', dest='ascii', action='store_false',
                        help="JIRA issues will not be output to the console.")

    parser.add_argument('-c', '--csv', dest='csv', nargs='?', type=str, choices=csv.list_dialects(), const='excel',
                        help="JIRA issues are output to a csv file 'jira.csv'. This flag takes an optional keyword "
                             "parameter that determines the format of the generated csv file.")

    args = parser.parse_args()

    # Convert list of domain keys into OrderedDict
    if isinstance(args.domains, list):
        domains = OrderedDict()
        for domain_key in args.domains:
            domains[domain_key] = JIRA_LOCATIONS[domain_key]
        args.domains = domains

    return args

if __name__ == '__main__':
    a = get_program_args()
    options = {'start_date': a.start_date, 'end_date': a.end_date, 'jira_limit': a.jira_limit, 'order': a.order,
               'user_roles': ['Assignee'], 'ascii': a.ascii}

    for user in a.usernames:
        if a.ascii:
            print("JIRA Issues Associated with {} at domains {}".format(user, list(a.domains)))

        # Only create a file if absolutely necessary
        if a.csv is not None:
            filename = "{}-jira.csv".format(user)
            with open(filename, mode='w') as csvfile:
                options['csv_writer'] = csv.writer(csvfile, dialect=a.csv)
                search_jira_domains(a.domains, user, **options)
        else:
            search_jira_domains(a.domains, user, **options)


# -*- coding: latin-1 -*-
import itertools
import numpy

import invariant_finder
import pddl
import timers

def expand_group(group, task, reachable_facts):
    result = []
    for fact in group:
        try:
            pos = list(fact.args).index("?X")
        except ValueError:
            result.append(fact)
        else:
            # NOTE: This could be optimized by only trying objects of the correct
            #       type, or by using a unifier which directly generates the
            #       applicable objects. It is not worth optimizing this at this stage,
            #       though.

            if len([a for a in fact.args if a == "?X"]) > 1:
                for pred in task.predicates:
                    if fact.predicate == pred.name:
                        predicate = pred
                        break

                arg_instanciated_obj = []
                index = 0
                for arg in fact.args:
                    arg_instanciated_obj.append([])
                    if arg == "?X":
                        for obj in task.objects:
                            if obj.type == predicate.arguments[index].type:
                                arg_instanciated_obj[index].append(obj.name)
                    else:
                        arg_instanciated_obj[index].append(arg)
                    index = index + 1

                all_possible_args = list(itertools.product(*arg_instanciated_obj))

                for newargs in all_possible_args:
                    atom = pddl.Atom(fact.predicate, newargs)
                    if atom in reachable_facts:
                        result.append(atom)

            else:
                for obj in task.objects:
                    newargs = list(fact.args)
                    newargs[pos] = obj.name
                    atom = pddl.Atom(fact.predicate, newargs)
                    if atom in reachable_facts:
                        result.append(atom)
    return result

def obtaing_const_args(groups):
    const_args = []
    for group in groups:
        const_group_args = []
        for atom in group:
            for arg in atom.args:
                if "?" not in arg and arg not in const_group_args:
                    const_group_args.append(arg)
        const_args.append(const_group_args)
    return const_args

def obtaing_const_args_funcs(groups, arguments):
    for group in groups:
        const_group_args = []
        if isinstance(group[0].predicate, pddl.f_expression.Increase) or \
                isinstance(group[0].predicate, pddl.f_expression.Decrease) or \
                isinstance(group[0].predicate, pddl.f_expression.Assign) or \
                isinstance(group[0].predicate, pddl.f_expression.GreaterThan) or \
                isinstance(group[0].predicate, pddl.f_expression.LessThan):
            name = group[0].predicate.fluent.symbol
            for arg in group[0].predicate.fluent.args:
                name = name + "-" + arg.name
            const_group_args.append(name)
            arguments.append(const_group_args)
    return arguments

def obtaing_const_args_extra(groups, arguments, reachable_facts):
    arguments_extra = []
    arguments_extra_list = []
    to_remove_list = []
    for group in groups:
        if not isinstance(group[0].predicate, str):
            arguments_extra.append([group[0].predicate.fluent.symbol])
            to_remove_list.append([])
            continue
        cands = {}
        to_remove = []
        for atom in group:
            if atom.predicate not in cands.keys():
                cands[atom.predicate] = []
                for arg in atom.args:
                    cands[atom.predicate].append(arg)
            else:
                if "_curr" in atom.predicate:
                    for arg in atom.args:
                        if arg not in cands[atom.predicate]:
                            cands[atom.predicate].append(arg)
                else:
                    arg_index = 0
                    for arg in atom.args:
                        if cands[atom.predicate][arg_index] != arg:
                            # if arg in cands[atom.predicate]:
                            #    cands[atom.predicate].remove(arg)
                            exists = False
                            for elem in to_remove:
                                if elem[0] == atom.predicate and elem[1] == arg:
                                    exists = True
                            if not exists:
                                to_remove.append([atom.predicate, cands[atom.predicate][arg_index]])
                                to_remove.append([atom.predicate, arg])
                        arg_index = arg_index + 1
        arguments_extra.append(cands)
        to_remove_list.append(to_remove)

    group_index = 0
    for arg_group in arguments_extra:
        arg_list = []
        if isinstance(arg_group, list):
            arguments_extra_list.append(arg_group)
            group_index = group_index + 1
            continue
        for pred, args in arg_group.items():
            for arg in args:
                if arg not in arg_list:
                    arg_list.append(arg)

        for arg in to_remove_list[group_index]:
            if arg[1] in arg_list:
                arg_list.remove(arg[1])

        arguments_extra_list.append(arg_list)
        group_index = group_index + 1

    return arguments_extra_list

def instantiate_groups(groups, task, reachable_facts):
    return [expand_group(group, task, reachable_facts) for group in groups]

def instantiate_function_groups(groups, task, functions):
    function_group_names = {}
    for func in functions:
        key = func.predicate.fluent.symbol + str(*func.predicate.fluent.args)
        if key not in function_group_names:
            function_group_names[key] = len(groups)
            groups.append([])
        if func not in groups[function_group_names[key]]:
            groups[function_group_names[key]].append(func)
    return groups

class GroupCoverQueue:
    def __init__(self, groups, arguments, partial_encoding):
        self.partial_encoding = partial_encoding
        if groups:
            self.max_size = max([len(group) for group in groups])
            self.groups_by_size = [[] for i in range(self.max_size + 1)]
            self.arguments = [[] for i in range(self.max_size + 1)]
            self.groups_by_fact = {}
            i = 0
            for group in groups:
                group = set(group)  # Copy group, as it will be modified.
                self.groups_by_size[len(group)].append(group)
                self.arguments[len(group)].append(arguments[i])
                for fact in group:
                    self.groups_by_fact.setdefault(fact, []).append(group)
                i = i + 1
            self._update_top()
        else:
            self.max_size = 0

    def __bool__(self):
        return self.max_size > 1

    def pop(self):
        result = list(self.top)  # Copy; this group will shrink further.
        if self.partial_encoding:
            for fact in result:
                for group in self.groups_by_fact[fact]:
                    group.remove(fact)
        self._update_top()
        return result

    def _update_top(self):
        while self.max_size > 1:
            max_list = self.groups_by_size[self.max_size]
            while max_list:
                candidate = max_list.pop()
                if len(candidate) == self.max_size:
                    self.top = candidate
                    return
                self.groups_by_size[len(candidate)].append(candidate)
            self.max_size -= 1

# I don't want to remove facts that have already been covered
# Thus, partial encoding is set to false for all cases
def choose_groups(groups, reachable_facts, functions, arguments, partial_encoding=False):
    queue = GroupCoverQueue(groups, arguments, partial_encoding=partial_encoding)
    uncovered_facts = reachable_facts.copy()

    # uncovered_funcs = functions.copy()
    result = []
    i = 0
    arguments_aux = []
    while queue:
        group = queue.pop()
        uncovered_facts.difference_update(group)
        result.append(group)

    for dummy in queue.arguments:
        if len(dummy):
            for arg in dummy:
                arguments_aux.append(arg)
    arguments_aux.reverse()

    for group in groups:
        if len(group) == 1 and isinstance(group[0].predicate, pddl.f_expression.Increase) and group not in result:
            result.append(group)

    print(len(uncovered_facts), "uncovered facts")
    # for fact in uncovered_facts:
    #  print fact
    result += [[fact] for fact in uncovered_facts]
    # result += [[func] for func in uncovered_funcs]
    return result, arguments_aux

def remove_func_redundant(groups, mutex_groups):
    index = 0
    removed = 0
    length = len(mutex_groups)
    for _ in range(length):
        if index >= len(groups):
            mutex_groups.pop(index - removed)
            removed = removed + 1
        index = index + 1

def build_translation_key(groups):
    group_keys = []
    for group in groups:
        group_key = [str(fact) for fact in group]
        group_key.append("<none of those>")
        group_keys.append(group_key)
    return group_keys

def collect_all_mutex_groups(groups, atoms, functions):
    # NOTE: This should be functionally identical to choose_groups
    # when partial_encoding is set to False. Maybe a future
    # refactoring could take that into account.
    all_groups = []
    uncovered_facts = atoms.copy()
    for group in groups:
        uncovered_facts.difference_update(group)
        all_groups.append(group)
    all_groups += [[fact] for fact in uncovered_facts]

    uncovered_funcs = functions.copy()
    all_groups += [[func] for func in uncovered_funcs]
    return all_groups

def compute_groups(task, atoms, functions, reachable_action_params, partial_encoding=False):
    groups = invariant_finder.get_groups(task, reachable_action_params)
    with timers.timing("Instantiating groups"):
        arguments = obtaing_const_args(groups)
        groups = instantiate_groups(groups, task, atoms)
    with timers.timing("Instantiating function groups"):
        groups = instantiate_function_groups(groups, task, functions)
        arguments = obtaing_const_args_funcs(groups, arguments)
    # TODO: I think that collect_all_mutex_groups should do the same thing
    #       as choose_groups with partial_encoding=False, so these two should
    #       be unified.
    with timers.timing("Collecting mutex groups"):
        mutex_groups = collect_all_mutex_groups(groups, atoms, functions)
    with timers.timing("Choosing groups", block=True):
        groups, arguments = choose_groups(groups, atoms, functions, arguments, partial_encoding=partial_encoding)
        arguments_ex = obtaing_const_args_extra(groups, arguments, atoms)
    with timers.timing("Removing redundant functional propositions"):
        remove_func_redundant(groups, mutex_groups)
    with timers.timing("Building translation key"):
        translation_key = build_translation_key(groups)
    return groups, mutex_groups, translation_key, arguments_ex, arguments

def get_fluents_in_runtime(groups):
    fluents_in_runtime = []
    dict_fluents_in_runtime = {}
    index = 0
    for group in groups:
        for item in group:
            if isinstance(item.predicate, pddl.f_expression.Increase) or \
                    isinstance(item.predicate, pddl.f_expression.Decrease) or \
                    isinstance(item.predicate, pddl.f_expression.Assign):
                fluents_in_runtime.append(item.predicate.fluent)
                dict_fluents_in_runtime[str(item.predicate.fluent)] = index
                break
        index = index + 1

    return fluents_in_runtime, dict_fluents_in_runtime


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Jul  2 15:42:35 2020

@author: sahyadri
"""

from astroquery.vizier import Vizier
import requests
from bs4 import BeautifulSoup
from astroquery.simbad import Simbad
import numpy as np
from astropy.table import Table, vstack
from astropy.io import ascii
from astropy import units as u
from astropy.coordinates import SkyCoord, get_constellation
import pandas as pd
import kaggle
from astroquery.gaia import Gaia
import glob, os

print('Downloading constellation_borders.csv...')
catalogue_list = Vizier.find_catalogs("Constellation")#This loads all the catalogs by the keyword "constellation"
Vizier.ROW_LIMIT = -1
catalog = Vizier.get_catalogs("VI/49")[1]#This selects the 2nd of three tables that were found by the key-word search. This table contains relevant data
catalog.remove_columns(['cst','type'])
coords = SkyCoord(catalog['RAJ2000'],catalog['DEJ2000'],unit="deg")
const = coords.get_constellation()
catalog.add_column(const,name="Constellation", index = 2)
catalog.write("constellation_borders.csv",format="csv",overwrite="True")
print('\n')
print('Done')
print('\n')
print('Downloading Messier Catalogue...')

#the next three lines are to simplify the output table
Simbad.reset_votable_fields()
Simbad.remove_votable_fields('coordinates')
Simbad.add_votable_fields('otype(3)', 'ra(d;A;ICRS;J2000;2000)', 'dec(d;D;ICRS;J2000;2000)','flux(B)','flux(V)')#These are all the columns added to the table

result_table = Simbad.query_catalog("Messier")#This asks the SIMBAD database to list all objects from the messier catalog
result_table['FLUX_V'].name = 'V'
result_table['OTYPE_3']=[x.decode('utf8') for x in result_table['OTYPE_3']]
result_table['MAIN_ID']=[x.decode('utf8') for x in result_table['MAIN_ID']]
result_table['RA_d_A_ICRS_J2000_2000'].name = "RAJ2000"
result_table['DEC_d_D_ICRS_J2000_2000'].name = "DEJ2000"
result_table['B-V'] = result_table['FLUX_B'] - result_table['V']
result_table.remove_column('FLUX_B')

coords = SkyCoord(result_table['RAJ2000'],result_table['DEJ2000'],unit="deg")
const = coords.get_constellation()
const_abr = coords.get_constellation(short_name = "True")
result_table.add_column(const,name="Constellation", index = 2)

otype = result_table['OTYPE_3']
internal_id = [otype[i]+'_'+const_abr[i]+'_'+str(i+1) for i in range(len(const))]
result_table.add_column(internal_id, name = "Internal ID Number", index = 0)

result_table.write("messier_objects.csv",format="csv",overwrite="True")#creates a csv file

Simbad.reset_votable_fields()#renders the prev changes to simbad class temporary.
print('\n')
print('Done')
print('\n')
print('Downloading NGC catalogue...')

#CHANGE GET_CONSTELLATION EQUINOX FROM B1875 TO 2000
v = Vizier(columns = ['Name','Type','mag','RA (deg)','Dec (deg)'])#Columns added to table
v.ROW_LIMIT = -1
result_table = v.get_catalogs("VII/118/ngc2000")[0]

result_table['Name'] = ['IC '+x[1:] if x[0]=='I' else 'NGC '+x for x in result_table['Name']]
result_table['Type'] = ['Gal' if x=='Gx' else 'OpC' if x=='OC' else 'GlC' if x=='Gb' else 'PN' if x=='Pl' else 'Str' if x=='*' or x=='D*' or x=='***' else '-' if x == '' or x=='-' or x=='?' else x for x in result_table['Type']]

coords = SkyCoord(result_table['_RAJ2000'],result_table['_DEJ2000'],unit="deg")
const = coords.get_constellation()
const_abr = coords.get_constellation(short_name = "True")
result_table.add_column(const,name="Constellation", index = 2)

otype = result_table['Type']
internal_id = [otype[i]+'_'+const_abr[i]+'_'+str(i+1) if otype[i]!='-' else 'notype'+'_'+const_abr[i]+'_'+str(i+1) for i in range(len(const))]
result_table.add_column(internal_id, name = "Internal ID Number", index = 0)
result_table.write("NGC.csv",format="csv",overwrite="True")

#cross catalogue for NGC
v = Vizier(columns = ['Object','Name'])
v.ROW_LIMIT = -1
v.TIMEOUT = 1000
cross_catalog = v.get_catalogs('VII/118/names')[0]
cross_catalog['Name'] =  ['IC '+x.split()[1] if len(x.split())==2 and x.split()[0]=="I" else 'IC'+x.split()[0][1:] if len(x.split())==1 and x.split()[0]=="I" else 'NGC '+x for x in cross_catalog['Name']]
cross_catalog.write("DsCrossCatalog.csv",format='csv',overwrite="True")

ccat = pd.read_csv('DsCrossCatalog.csv')
ccat = pd.DataFrame(ccat)
ccat = ccat.loc[~ccat.Name.duplicated(keep='first')]
ntable= pd.read_csv('NGC.csv')
ntable = pd.DataFrame(ntable)
ntable.insert(2,"Common Name",np.zeros(len(ntable['_RAJ2000'])))
ntable['Common Name'] = ntable.Name.map(ccat.set_index('Name').Object,na_action="ignore")
ntable.to_csv('NGC.csv')
ntable = Table.read('NGC.csv')
ntable.remove_columns(['col0'])
ntable.write('NGC.csv',format='csv',overwrite="True")

print('\n')
print('Done')
print('\n')

#Download the star name file
kaggle.api.authenticate()
kaggle.api.dataset_download_files('ecotner/named-stars/IAU-CSN.csv', path='/home/sahyadri/Desktop/Star-Hopping', unzip=True)

#CROSS CATALOG
v = Vizier(columns = ['HD','TYC','HIP','Vmag','Fl','Bayer','Cst'])
v.ROW_LIMIT = -1
v.TIMEOUT = 1000
cross_catalog = v.get_catalogs('IV/27A/catalog')[0]
bayer_const = [x['Bayer']+' '+x['Cst'] for x in cross_catalog]
cross_catalog.remove_columns("Bayer")
cross_catalog['BayerConst'] = bayer_const
cross_catalog.write("CrossCatalog.csv",format='csv',overwrite="True")

print('Tycho-2 Catalogue')

run_count = 0
run = True
last_id = 0
while run:

    MinVmag = input('(INT ONLY) Input minimum value of Vmag (skippable) ',)
    MaxVmag = int(input('(INT ONLY) Input maximum value of Vmag ',))

    if type(MaxVmag)!=int:
        print("invalid entry")
        continue
    if MinVmag!='':
        MinVmag = int(MinVmag)

    run_count = run_count +1
    if MinVmag=='':
        filter_input = "<{}".format(MaxVmag)
    else:
        filter_input = "{}..{}".format(MinVmag, MaxVmag)

    v = Vizier(columns = ['HIP','TYC','HD','_RAJ2000','DECJ2000','+Vmag','B-V'], column_filters = {"Vmag":"{}".format(filter_input)})
    v.ROW_LIMIT = 1000000000
    v.TIMEOUT = 1000
    catalog_stars = v.get_catalogs("I/239/tyc_main")[0]
    catalog_stars['Vmag'].name = "V"

    coords = SkyCoord(catalog_stars['_RAJ2000'],catalog_stars['_DEJ2000'],unit="deg")
    const = coords.get_constellation()
    const_abr = coords.get_constellation(short_name = "True")

    catalog_stars.add_column(const,name="Constellation", index = 0)

    internal_id = ["Str_"+const_abr[i]+"_"+f"{i+last_id+1:08d}" for i in range(len(catalog_stars['_RAJ2000']))]
    catalog_stars.add_column(internal_id, name="Internal ID Number", index = 0)

    catalog_stars.write("tycho_{}.csv".format(run_count),format="csv",overwrite = "True")
    last_id = last_id + len(catalog_stars['_RAJ2000'])

    #Adding common names to the stars
    names_table = pd.read_csv('IAU-CSN.csv')
    names_table = pd.DataFrame(names_table)
    ttable = pd.read_csv('tycho_{}.csv'.format(run_count))
    ttable = pd.DataFrame(ttable)
    names_table["HIP"] = [x if x!='-' else 0 for x in names_table["HIP"]]
    ttable.insert(1,"Name",np.zeros(len(ttable['TYC'])))
    names_table["HIP"] = pd.to_numeric(names_table['HIP'],errors='coerce')
    ttable['Name'] = ttable.HIP.map(names_table.set_index('HIP').Name)
    ttable.to_csv('tycho_{}.csv'.format(run_count))

    #The cross cataloguing part
    ccat = pd.read_csv('CrossCatalog.csv')
    ccat = pd.DataFrame(ccat)
    ccat["HIP"].fillna("0", inplace = True)
    ttable = pd.read_csv('tycho_{}.csv'.format(run_count))
    ttable = pd.DataFrame(ttable)
    ccat = ccat.loc[~ccat.HIP.duplicated(keep='first')]
    ttable.insert(4,"Bayer",np.zeros(len(ttable['_RAJ2000'])))
    ttable['Bayer'] = ttable.HIP.map(ccat.set_index('HIP').BayerConst,na_action="ignore")
    ttable.to_csv('tycho_{}.csv'.format(run_count))
    ttable = Table.read('tycho_{}.csv'.format(run_count))
    ttable.remove_columns(['col0','Unnamed: 0'])
    ttable.write('tycho_{}.csv'.format(run_count),format='csv',overwrite="True")

    while True:
        status = input("Another run of Tycho database download? (y/n)",)
        if status == "n":
            run = False
            break
        elif status == "y":
            run = True
            break
        else:
            print("invalid answer")

name_list = []
for file in glob.glob("tycho_*.csv"):
    name_list.append(file)
name_list.sort()
t = pd.concat([pd.read_csv(i) for i in name_list])
t.to_csv('tycho.csv')

print('Done')
print('\n')
g_status = input('Gaia - Do you want to skip? (y/n)',)
while True:
    if g_status == "y":
        g_run = False
        break
    elif g_status == "n":
        g_run = True
        break
    else:
        print('invalid answer')

run_count = 0
while g_run:
    print('Gaia dr1 catalogue')

    MinVmag = input('(INT ONLY) Input minimum value of Vmag (skippable)',)
    MaxVmag = int(input('(INT ONLY) Input maximum value of Vmag',))
    if type(MaxVmag)==int:
        break
    else:
        print("invalid entry")
        continue
    if MinVmag!='':
        MinVmag = int(MinVmag)

    if MinVmag=='':
        filter_input = "<{}".format(MaxVmag)
    else:
        filter_input = "between {} and {}".format(MinVmag, MaxVmag)
    run_count = run_count + 1

    Gaia.ROW_LIMIT = -1

    job = Gaia.launch_job_async("select ra,dec,phot_g_mean_mag from gaiadr1.gaia_source where (phot_g_mean_mag {}) order by phot_g_mean_mag".format(filter_input))
    r = job.get_results()
    r.write('gaia.csv',format='csv',overwrite="True")
    while True:
        status = input("Another run of Gaia database download? (y/n)",)
        if status == "n":
            g_run = False
            break
        elif status == "y":
            g_run = True
            break
        else:
            print("invalid answer")
print('Done')


from datetime import date
now=date.today()
print(date.today())
dob_en=input("enter your birth date in yyyy-m-dd format eg.1995-2-13")
dob_en=dob_en.split("-")
"""for i in dob_en:
    i=int(i)
    print(i)
    print("value of ",i,": ",type(i))
 """
dob=date(int(dob_en[0]),int(dob_en[1]),int(dob_en[2]))
age=now-dob
print("Date of birth: ",dob)
print("Today`s date:",now)
print("Age in days:",age)


from scipy.spatial import distance as dist
from collections import OrderedDict
import numpy as np

class CentroidTracker():
        def __init__(self, maxDisappeared=50):
                # initialize the next unique object ID along with two ordered
                # dictionaries used to keep track of mapping a given object
                # ID to its centroid and number of consecutive frames it has
                # been marked as "disappeared", respectively
                self.nextObjectID = 0
                self.objects = OrderedDict() # 삽입순서를 보존하는 딕셔너리
                self.disappeared = OrderedDict()

                # store the number of maximum consecutive frames a given
                # object is allowed to be marked as "disappeared" until we
                # need to deregister the object from tracking
                self.maxDisappeared = maxDisappeared

        def register(self, centriod):
                self.objects[self.nextObjectID] = centriod
                self.disappeared[self.nextObjectID] = 0
                self.nextObjectID += 1

        def deregister(self, objectID):
                del self.objects[objectID]
                del self.disappeared[objectID]

        def update(self, points):

                if len(points) == 0:
                    # loop over any existing tracked objects and mark them
                    # as disappeared

                    for objectID in list(self.disappeared.keys()):
                        self.disappeared[objectID] += 1
                        #일정 프레임동안 disappeared이면 deregister
                        if self.disappeared[objectID] > self.maxDisappeared:
                            self.deregister(objectID)

                    return self.objects

                inputCentroids = np.zeros((len(points), 2), dtype = "int")

                for(i, (cX,cY)) in enumerate(points):
                        inputCentroids[i] = (cX, cY)

                # 현재 트래킹하고있는 물체가 없다면 추가해줌
                if len(self.objects)== 0 :

                        for i in range(0, len(inputCentroids)):
                                self.register(inputCentroids[i])

                else:

                #현재 트래킹하는 물체가 있다면, 현존하는 물체들의 중심과 input centroids의 중심을 매칭시켜줌

                        objectIDs = list(self.objects.keys())
                        objectCentroids = list(self.objects.values())
                        #물체들의 중심과 input centroids간의 거리를 모두  계산
                        # D.shape = (# of object centroids, # of input cen4troids)
                        D = dist.cdist(np.array(objectCentroids), inputCentroids)
                        #1. find the smallest value in each row
                        #2. sort the row indexes based on their min values so that
                        #   the row w/ the smallest value is at the front of the index list
                        # min(axis=1)은 같은 행에 속한 숫자들끼지 비교, argsort는 크기순서를 나타냄
                        # 즉 각 row에 속한 숫자들 중에 가장 작은 숫자를 뽑아내고, 그 숫자들의 크기순서 나타낸 index배열 반환.
                        rows = D.min(axis=1).argsort()
                        #finding the smallest value in each colunm and sorting using row index list
                        # argmin(axis=1)은 같은 행에 속한 숫자들끼지 비교하고 min의 index리턴
                        # index배열
                        cols = D.argmin(axis=1)[rows]

                        #해당 row,col의 인덱스가 이미 사용되었는지 확인
                        usedRows = set()
                        usedCols = set()

                        for (row, col) in zip(rows, cols):
                            if row in usedRows or col in usedCols:#이미 있으면 무시
                                continue

                            objectID = objectIDs[row]
                            self.objects[objectID] = inputCentroids[col] # set its new centroid
                            self.disappeared[objectID] = 0 #reset the disapppeared counter

                            usedRows.add(row)
                            usedCols.add(col)

                        #difference function : 차집합
                        unusedRows = set(range(0, D.shape[0])).difference(usedRows)
                        unusedCols = set(range(0, D.shape[1])).difference(usedCols)

                        if D.shape[0] >= D.shape[1]:#objects가 사라졌거나 lost됐다
                            for row in unusedRows:
                                objectID = objectIDs[row]
                                self.disappeared[objectID] += 1

                                if self.disappeared[objectID] > self.maxDisappeared:
                                    self.deregister(objectID)

                        else:#새 object가 생겼다
                            for col in unusedCols:
                                self.register(inputCentroids[col])

                return self.objects


import cv2
import os
import sys
from mrcnn import utils
from mrcnn import model as modellib
from mrcnn.config import Config
from mrcnn.visualize import *
import mrcnn.model as modellib
from mrcnn.model import MaskRCNN
import uuid
import argparse
import skimage
import colorsys
import tensorflow as tf
import numpy as np
import shutil
import random
import argparse
from skimage import io
import uuid

NUM_CATS = 46
IMAGE_SIZE = 512

class FashionConfig(Config):
    NAME = "fashion"
    GPU_COUNT = 1
    IMAGES_PER_GPU = 1
    NUM_CLASSES = NUM_CATS + 1
    BACKBONE = 'resnet50'

    IMAGE_MIN_DIM = IMAGE_SIZE
    IMAGE_MAX_DIM = IMAGE_SIZE
    IMAGE_RESIZE_MODE = 'none'
    RPN_ANCHOR_SCALES = (16, 32, 64, 128, 256)

config = FashionConfig()

ap = argparse.ArgumentParser()
ap.add_argument("-i", "--input", required=True)
ap.add_argument("-o", "--output", required=True)
args = vars(ap.parse_args())

input_image_dir = args["input"]
output_image_dir = args["output"]

model = modellib.MaskRCNN(mode="inference", config=config, model_dir=config.MODEL_DIR)
model.load_weights(config.MODEL_PATH, by_name=True)

def resize_image(image_path):
    img = cv2.imread(image_path)
    img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    img = cv2.resize(img, (IMAGE_SIZE, IMAGE_SIZE), interpolation=cv2.INTER_AREA)
    return img

def refine_masks(masks, rois):
    areas = np.sum(masks.reshape(-1, masks.shape[-1]), axis=0)
    mask_index = np.argsort(areas)
    union_mask = np.zeros(masks.shape[:-1], dtype=bool)
    for m in mask_index:
        masks[:, :, m] = np.logical_and(masks[:, :, m], np.logical_not(union_mask))
        union_mask = np.logical_or(masks[:, :, m], union_mask)
    for m in range(masks.shape[-1]):
        mask_pos = np.where(masks[:, :, m] == True)
        if np.any(mask_pos):
            y1, x1 = np.min(mask_pos, axis=1)
            y2, x2 = np.max(mask_pos, axis=1)
            rois[m, :] = [y1, x1, y2, x2]
    return masks, rois

for filename in os.listdir(input_image_dir):
    if filename.lower().endswith(('.png', '.jpg', '.jpeg', '.tiff', '.bmp', '.gif')):
        image_path = os.path.join(input_image_dir, filename)
        print(image_path)
        img = io.imread(image_path)
        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        result = model.detect([resize_image(image_path)])
        r = result[0]
        if r['masks'].size > 0:
            masks = np.zeros((img.shape[0], img.shape[1], r['masks'].shape[-1]), dtype=np.uint8)
            for m in range(r['masks'].shape[-1]):
                masks[:, :, m] = cv2.resize(r['masks'][:, :, m].astype('uint8'),
                                            (img.shape[1], img.shape[0]), interpolation=cv2.INTER_NEAREST)
            y_scale = img.shape[0] / IMAGE_SIZE
            x_scale = img.shape[1] / IMAGE_SIZE
            rois = (r['rois'] * [y_scale, x_scale, y_scale, x_scale]).astype(int)

            masks, rois = refine_masks(masks, rois)
        else:
            masks, rois = r['masks'], r['rois']

        save_masked_instances(output_image_dir, img, rois, masks, r['class_ids'], ['bg'] + config.LABEL_NAMES, r['scores'],
                              title='image_id',
                              figsize=(16, 16))


# -*- coding: utf-8 -*-
"""
Created on Tue Jun  8 20:04:16 2021

@author: Meva
"""

import numpy as np
import pandas as pd
import matplotlib as mpl
import scipy
import importlib
import matplotlib.pyplot as plt
from scipy.stats import skew, kurtosis, chi2

# import our own files and reload
import file_functions
importlib.reload(file_functions)
import file_classes
importlib.reload(file_classes)

# inputs
inputs = file_classes.option_input()
inputs.volatility = 0.1442
inputs.interest_rate = 0.0158
inputs.maturity = 1 # in years
inputs.strike = 20
inputs.call_or_put = 'call'

radius = 0.10
inputs.price =  np.linspace(1-radius,1+radius,1000) * inputs.strike
months = [0,3,6,9,11]
dict_plots = {}

# compute option prices
for month in months:
    # compute option prices
    inputs.time = float(month) / (12 * inputs.maturity)
    price_black_scholes = file_functions.compute_price_black_scholes(inputs)
    dict_plots[month] = price_black_scholes

# compute payoff
if inputs.call_or_put == 'call':
    payoff = np.array([max(s - inputs.strike, 0.0) for s in inputs.price])
elif inputs.call_or_put == 'put':
    payoff = np.array([max(inputs.strike - s, 0.0) for s in inputs.price])

# plot option prices
plt.figure()
plt.title('Plot of option prices | ' + inputs.call_or_put)
for month in months:
    plt.plot(inputs.price, dict_plots[month], label = str(month) + '-month')
plt.plot(inputs.price, payoff, label = 'payoff')
plt.ylabel('price option')
plt.xlabel('price underlying')
plt.legend()
plt.grid()
plt.show()


from typing import List
from collections import Counter

class Solution:
    def onesMinusZeros(self, grid: List[List[int]]) -> List[List[int]]:
        rows = len(grid)
        columns = len(grid[0])
        diff = [[0] * columns for _ in range(rows)]

        ones_row = [sum(row) for row in grid]
        zeros_row = [columns - ones for ones in ones_row]
        ones_col = [sum(row[j] for row in grid) for j in range(columns)]
        zeros_col = [rows - ones for ones in ones_col]

        for i in range(rows):
            for j in range(columns):
                diff[i][j] = ones_row[i] + ones_col[j] - zeros_row[i] - zeros_col[j]

        return diff

grid = [[0,1,1],[1,0,1],[0,0,1]]
sol1 = Solution()
result = sol1.onesMinusZeros(grid)
print(result)