#"""Build and train for the AI Models."""
#imports
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import argparse
import datetime
import os
from data_load import DataLoader
import numpy as np
import tensorflow as tf

model_name = ""

def reshape_function(data, label):
  reshaped_data = tf.reshape(data, [-1, 10, 1])
  return reshaped_data, label

def calculate_model_size(model):
  print(model.summary())
  var_sizes = [
      np.product(list(map(int, v.shape))) * v.dtype.size
      for v in model.trainable_variables
  ]
  print("Model size:", sum(var_sizes) / 1024, "KB")

def build_cnn(seq_length):
  """Builds a convolutional neural network in Keras."""
  global model_name

  if args.modelnumber == "0":
    model_name = "-CNN_model-0"
    model = tf.keras.Sequential()
    model.add(tf.keras.layers.Conv2D(
            10, (20, 10),
            padding="same",
            activation="relu",
            input_shape=(seq_length, 10, 1)))
    model.add(tf.keras.layers.MaxPooling2D((3, 3)))
    model.add(tf.keras.layers.Flatten())
    model.add(tf.keras.layers.Dense(9, activation='linear'))
    model.summary()
  elif args.modelnumber == "1":
    model_name = "-CNN_model-1"
    model = tf.keras.Sequential([
      tf.keras.layers.Conv2D(
          10, (20, 10),
          padding="same",
          activation="relu",
          input_shape=(seq_length, 10, 1)),
      tf.keras.layers.MaxPool2D((3, 3)),
      tf.keras.layers.Dropout(0.1),
      tf.keras.layers.Conv2D(16, (10, 1), padding="same",
                             activation="relu"),
      tf.keras.layers.MaxPool2D((3, 1), padding="same"),
      tf.keras.layers.Dropout(0.1),
      tf.keras.layers.Flatten(),
      tf.keras.layers.Dense(16, activation="relu"),
      tf.keras.layers.Dropout(0.1),
      tf.keras.layers.Dense(9, activation="relu")
    ])

  model_path = os.path.join("./netmodels", "CNN")
  print("Built CNN.")
  if not os.path.exists(model_path):
    os.makedirs(model_path)
  return model, model_path

def build_lstm(seq_length):
  """Builds an LSTM in Keras."""
  #LSTM Sequential model with 2 layers, 100 neurons in first layer after it a flatten and then a dense-layer with 9 neurons
  #Best performing model till now 28.11.2023 14:26
  #RMSE 1.4 -> but no accurate predictions epochs 30 -> seq 20 -> batch 64
  #Loss: 0.939727783203125, RMSE: 0.9693955779075623 -> epochs 30 -> batch 64 -> seq 20

  global model_name

  #TODO add modelnumber to foldername
  if args.modelnumber == "0":
    model_name = "-LSTM_model-0"
    model = tf.keras.Sequential([
            tf.keras.Input(shape=(seq_length, 10)),
            tf.keras.layers.LSTM(100),
            tf.keras.layers.Dense(units=9, activation="linear"),
        ])
    model.summary()
  if args.modelnumber == "1":
    model_name = "-LSTM_model-1"
    model = tf.keras.Sequential([
            tf.keras.Input(shape=(seq_length, 10)),
            tf.keras.layers.LSTM(100),
            tf.keras.layers.Flatten(),
            tf.keras.layers.Dense(units=9, activation="linear"),
        ])
    model.summary()
  elif args.modelnumber == "2":
    model_name = "-LSTM_model-2"
    #LSTM Sequential model with 2 layers, 100 neurons in first layer after it a Dropoutlayer with 20% and then a dense-layer with 9 neurons
    model = tf.keras.Sequential([
          tf.keras.Input(shape=(seq_length, 10)),
          tf.keras.layers.LSTM(100),
          tf.keras.layers.Dropout(0.2),
          tf.keras.layers.Dense(units=9, activation="linear"),
      ])
    model.summary()
  elif args.modelnumber == "3":
    model_name = "-LSTM_model-3"
    model = tf.keras.Sequential([
        tf.keras.Input(shape=(seq_length, 10)),
        tf.keras.layers.LSTM(100),
        tf.keras.layers.Dropout(0.2),
        tf.keras.layers.Dense(units=9, activation="softmax"),
    ])
    model.summary()
  elif args.modelnumber == "4":
    model_name = "-LSTM_model-4"
    #LSTM Sequential model with 3 layers, 100 neurons in first layer, 100 neurons in second layer and then a dense-layer with 9 neurons
    model = tf.keras.Sequential([
        tf.keras.Input(shape=(seq_length, 10)),
        tf.keras.layers.LSTM(100, return_sequences = True),
        tf.keras.layers.LSTM(100),
        tf.keras.layers.Dense(units=9, activation="linear"),
    ])
    model.summary()
  elif args.modelnumber == "5":
    model_name = "-LSTM_model-5"
    model = tf.keras.Sequential([
    tf.keras.layers.Bidirectional(
        tf.keras.layers.LSTM(100, return_sequences = True),
        input_shape=(seq_length, 10)),
        tf.keras.layers.Dropout(0.2),
        tf.keras.layers.LSTM(100),
      tf.keras.layers.Dense(units=9, activation="linear")
    ])

  model_path = os.path.join("./netmodels", "LSTM")
  print("Built LSTM.")
  if not os.path.exists(model_path):
    os.makedirs(model_path)
  return model, model_path

def load_data(train_data_path, valid_data_path, test_data_path, seq_length):
  data_loader = DataLoader(
      train_data_path, valid_data_path, test_data_path, seq_length=seq_length)
  data_loader.format()
  return data_loader.train_len, data_loader.train_data, data_loader.valid_len, \
      data_loader.valid_data, data_loader.test_len, data_loader.test_data

def build_net(args, seq_length):
  if args.model == "CNN":
    model, model_path = build_cnn(seq_length)
  elif args.model == "LSTM":
    model, model_path = build_lstm(seq_length)
  else:
    print("Please input correct model name.(CNN  LSTM)")
  return model, model_path

def train_net(
    model,
    model_path,  # pylint: disable=unused-argument
    train_len,  # pylint: disable=unused-argument
    train_data,
    valid_len,
    valid_data,  # pylint: disable=unused-argument
    test_len,
    test_data,
    kind):

  """Trains the model."""
  calculate_model_size(model)
  #tested batch_sizes = 64, 128, 16, 10, 64
  #RMSE 1,7 -> 10 epochs -> batch 64 -> sequenc 20
  epochs = 30
  #The batch_size argument specifies how many pieces of training data to feed into the network before measuring its accuracy and updating its weights and biases.
  batch_size = 64

  rmse = tf.keras.metrics.RootMeanSquaredError()
  model.compile(
    optimizer='adam',
    loss='mse',
    metrics=[tf.keras.metrics.RootMeanSquaredError(), "accuracy"])

  if kind == "CNN":
    train_data = train_data.map(reshape_function)
    test_data = test_data.map(reshape_function)
    valid_data = valid_data.map(reshape_function)
  test_labels = np.zeros(test_len)
  idx = 0
  for data, label in test_data:  # pylint: disable=unused-variable
    test_labels[idx] = label.numpy()
    print(str(label))
    idx += 1

  #load train_data_entry for test
  print("--> trainTest_labels: ")
  trainTest_labels = np.zeros(train_len)
  idx = 0
  for data, label in train_data:  # pylint: disable=unused-variable
    trainTest_labels[idx] = label.numpy()
    print(str(label))
    idx += 1
  trainTest_data = train_data.batch(batch_size)

  train_data = train_data.batch(batch_size).repeat()
  valid_data = valid_data.batch(batch_size)
  test_data = test_data.batch(batch_size)

  #EaelyStop
  #EarlyStopping() saves us a lot of time, it stops the model training once it realizes that there will be no more decrease in loss in further epochs and training can now be stopped earlier than described epochs.
  early_stop = tf.keras.callbacks.EarlyStopping(monitor = 'val_loss', patience = 2)

  model.fit(
      train_data,
      epochs=epochs,
      validation_data=valid_data,
      steps_per_epoch=1000,
      #validation_steps=int((valid_len - 1) / batch_size + 1),
      validation_steps=1,
      #callbacks=[tensorboard_callback, early_stop])
      callbacks=[tensorboard_callback])
  loss, rmse, acc= model.evaluate(test_data)
  pred = np.argmax(model.predict(test_data), axis=1)
  print("\n\n\n TEST PREDICTION \n\n\n")
  print("\n Prediction should be:")
  print(test_labels)
  print("\n Prediction")
  print(pred)
  print("\n\n\n TEST PREDICTION END \n\n\n")
  #num_classes: The possible number of labels the classification task can
  confusion = tf.math.confusion_matrix(
      labels=tf.constant(test_labels),
      predictions=tf.constant(pred),
      num_classes=9)
  print(confusion)
  print("Loss: {}, RMSE: {}, Accuracy: {}".format(loss, rmse, acc))
  # Convert the model to the TensorFlow Lite format without quantization
  converter = tf.lite.TFLiteConverter.from_keras_model(model)

  converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS]
  converter._experimental_lower_tensor_list_ops = False

  tflite_model = converter.convert()

  # Save the model to disk
  open("model.tflite", "wb").write(tflite_model)

  # Convert the model to the TensorFlow Lite format with quantization
  converter = tf.lite.TFLiteConverter.from_keras_model(model)
  converter.optimizations = [tf.lite.Optimize.OPTIMIZE_FOR_SIZE]

  converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS, tf.lite.OpsSet.SELECT_TF_OPS]
  converter._experimental_lower_tensor_list_ops = False

  tflite_model = converter.convert()

  # Save the model to disk
  open("model_quantized.tflite", "wb").write(tflite_model)

  basic_model_size = os.path.getsize("model.tflite")
  print("Basic model is %d bytes" % basic_model_size)
  quantized_model_size = os.path.getsize("model_quantized.tflite")
  print("Quantized model is %d bytes" % quantized_model_size)
  difference = basic_model_size - quantized_model_size
  print("Difference is %d bytes" % difference)

if __name__ == "__main__":

  #print("Num GPUs Available: ", len(tf.config.list_physical_devices('GPU')))

  parser = argparse.ArgumentParser()
  parser.add_argument("--model", "-m")
  parser.add_argument("--modelnumber", "-mn")
  args = parser.parse_args()
  #args.model = "LSTM"
  #args.modelnumber = "0"

  #seq_length data window sizes tested = 2988, 128, 640, 64, 10
  #wenn die seq_length sehr klein model ungenauer bzw größerer RMSE ??? why -> weil das fenster zu klein und das model somit keinen gescheiten zusammenhang erkennen kann ??
  #seq_length = 128 -> RMSE 1.378 -> early stop 17 epochs
  #seq_length = 20 # RMSE LSTM -> 2.3 -> 10 Epochs
  #seq_length = 128 # RMSE LSTM -> 1.7 -> 10 Epochs
  seq_length = 20

  print("Start to load data...")
  train_len, train_data, valid_len, valid_data, test_len, test_data = \
          load_data("./Data/train/train.json", "./Data/valid/valid.json", "./Data/test/test.json", seq_length)

  print("Start to build net...")
  model, model_path = build_net(args, seq_length)

  logdir = "logs/scalars/" + datetime.datetime.now().strftime("%Y%m%d-%H%M%S") + model_name
  tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir=logdir)

  print("Start training...")
  train_net(model, model_path, train_len, train_data, valid_len, valid_data,
              test_len, test_data, args.model)

  print("Training finished!")

#LIST OF TESTED LSTM MODELS
  """
  #Loss: 2.5077505111694336, RMSE: 1.583587884902954 -> 5 epochs
  model = tf.keras.Sequential([
      tf.keras.layers.Bidirectional(
          tf.keras.layers.LSTM(20),
          input_shape=(seq_length, 10)),  # output_shape=(batch, 44)
          #tf.keras.layers.Dropout(0.2),
          #tf.keras.layers.Flatten(),
      tf.keras.layers.Dense(11, activation="sigmoid")  # (batch, 4)
  ])

  model.summary()
  """

  """
  #good model 2 -> RMSE 1.4 ohne dropout layer 24epochs batch 64 seq 20-> mit dropout layer RMSE
  #22.11.2023 - 14:34
  model = tf.keras.Sequential([
      tf.keras.layers.Bidirectional(
          tf.keras.layers.LSTM(100, return_sequences = True),
          input_shape=(seq_length, 10)),  # output_shape=(batch, 44)
          tf.keras.layers.LSTM(100),
          tf.keras.layers.Dropout(0.2),
      #tf.keras.layers.Dense(11, activation="sigmoid")  # (batch, 4)
      tf.keras.layers.Dense(11)#, activation="relu")  # (batch, 4)
      #tf.keras.layers.Dense(11, activation="linear")  # (batch, 4)
  ])
  """

  """
  model = tf.keras.Sequential([
      tf.keras.layers.InputLayer((seq_length,15)),
      #tf.keras.layers.LSTM(100, return_sequences = True),
      tf.keras.layers.LSTM(100),
      #tf.keras.layers.LSTM(50),
      #tf.keras.layers.Dense(8, activation = 'relu'),
      #tf.keras.layers.Dense(30, activation = 'relu'),
      tf.keras.layers.Dense(11, activation = 'linear')
      #tf.keras.layers.Dense(11, activation = 'softmax')
  ])
  """
  """
  model = tf.keras.Sequential([
      tf.keras.layers.InputLayer((seq_length,15)),
      #tf.keras.layers.LSTM(100, return_sequences = True),
      tf.keras.layers.LSTM(15, return_sequences = True),
      tf.keras.layers.LSTM(30),
      tf.keras.layers.Dense(15),
      #tf.keras.layers.LSTM(50),
      #tf.keras.layers.Dense(8, activation = 'relu'),
      #tf.keras.layers.Dense(30, activation = 'relu'),
      ##tf.keras.layers.Dropout(0.1),
      ##tf.keras.layers.Flatten(),
      tf.keras.layers.Dense(11, activation = 'softmax')
      #tf.keras.layers.Dense(11, activation = 'softmax')
  ])
  """
  """
  n_features = 15

  model = tf.keras.Sequential()

  model.add(tf.keras.layers.InputLayer((seq_length,n_features)))
  model.add(tf.keras.layers.LSTM(15, return_sequences = True))
  model.add(tf.keras.layers.LSTM(100, return_sequences = True))
  model.add(tf.keras.layers.LSTM(50))
  #model.add(tf.keras.layers.Dense(8, activation = 'relu'))
  model.add(tf.keras.layers.Dense(11, activation = 'linear'))

  model.summary()
  """
  """
  #seq 2000 batch 16 -> RMSE 1.41 after 6 epochs
  n_features = 15

  model = tf.keras.Sequential()

  model.add(tf.keras.layers.InputLayer((seq_length,n_features)))
  model.add(tf.keras.layers.LSTM(100))
  #model.add(tf.keras.layers.LSTM(100, return_sequences = True))
  #model.add(tf.keras.layers.LSTM(50))
  #model.add(tf.keras.layers.Dense(8, activation = 'relu'))
  model.add(tf.keras.layers.Dense(11, activation = 'linear'))

  model.summary()
  """
  """
  n_features = 15

  model = tf.keras.Sequential()
  model.add(tf.keras.layers.Bidirectional(
          tf.keras.layers.LSTM(100),
          input_shape=(seq_length, 15)))
  ##model.add(tf.keras.layers.InputLayer((seq_length,n_features)))
  ##model.add(tf.keras.layers.LSTM(100))
  ###model.add(tf.keras.layers.LSTM(100))
  ###model.add(tf.keras.layers.LSTM(100))
  #model.add(tf.keras.layers.LSTM(100, return_sequences = True))
  #model.add(tf.keras.layers.LSTM(50))
  #model.add(tf.keras.layers.Dense(8, activation = 'relu'))
  model.add(tf.keras.layers.Dropout(0.1))
  model.add(tf.keras.layers.Flatten())
  model.add(tf.keras.layers.Dense(11, activation="linear"))

  model.summary()
  """
  """
  #WORKING 0.9 RMSE
  model = tf.keras.Sequential([
      tf.keras.layers.InputLayer((seq_length,15)),
      tf.keras.layers.LSTM(100, return_sequences = True),
      tf.keras.layers.LSTM(100, return_sequences = True),
      tf.keras.layers.LSTM(50),
      #tf.keras.layers.Dense(8, activation = 'relu'),
      tf.keras.layers.Dense(30, activation = 'relu'),
      tf.keras.layers.Dense(11, activation = 'linear')
      #tf.keras.layers.Dense(11, activation = 'softmax')
  ])
  """

  """
  model = tf.keras.Sequential([
          tf.keras.layers.Bidirectional(
          tf.keras.layers.LSTM(100),
          input_shape=(seq_length, 15)),
    #tf.keras.layers.LSTM(100, return_sequences = True),
    #tf.keras.layers.LSTM(100, return_sequences = True),
    #tf.keras.layers.LSTM(50),
    tf.keras.layers.Dense(8, activation = 'relu'),
    tf.keras.layers.Dense(1, activation = 'linear')
  ])
  """

  """
  model = tf.keras.Sequential
  model.add(tf.keras.layers.InputLayer((seq_length,15)))
  model.add(tf.keras.layers.LSTM(100, return_sequences = True))
  model.add(tf.keras.layers.LSTM(100, return_sequences = True))
  model.add(tf.keras.layers.LSTM(50))
  model.add(tf.keras.layers.Dense(8, activation = 'relu'))
  model.add(tf.keras.layers.Dense(1, activation = 'linear'))
  """

  #LIST OF TESTED CNN MODELS
  """
  model_0 = tf.keras.Sequential(
    [
        #tf.keras.layers.Input(shape=input_shape),
        tf.keras.layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_uniform', padding='same'),
        tf.keras.layers.BatchNormalization(),
        tf.keras.layers.Conv2D(32, (3, 3), activation='relu', kernel_initializer='he_uniform', padding='same'),
        tf.keras.layers.BatchNormalization(),
        tf.keras.layers.MaxPooling2D((2, 2)),
        tf.keras.layers.Dropout(0.2),
        tf.keras.layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_uniform', padding='same'),
        tf.keras.layers.BatchNormalization(),
        tf.keras.layers.Conv2D(64, (3, 3), activation='relu', kernel_initializer='he_uniform', padding='same'),
        tf.keras.layers.BatchNormalization(),
        tf.keras.layers.MaxPooling2D((2, 2)),
        tf.keras.layers.Dropout(0.3),
        tf.keras.layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_uniform', padding='same'),
        tf.keras.layers.BatchNormalization(),
        tf.keras.layers.Conv2D(128, (3, 3), activation='relu', kernel_initializer='he_uniform', padding='same'),
        tf.keras.layers.BatchNormalization(),
        tf.keras.layers.MaxPooling2D((2, 2)),
        tf.keras.layers.Dropout(0.4),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(128, activation='relu', kernel_initializer='he_uniform'),
        tf.keras.layers.BatchNormalization(),
        tf.keras.layers.Dropout(0.5),
        #tf.keras.layers.Dense(num_classes_0, activation='softmax')
    ]
  )
  """

  """
  #good model
  n_features = 10

  model = tf.keras.Sequential()

  model.add(tf.keras.layers.InputLayer((seq_length,n_features)))
  #model.add(tf.keras.layers.BatchNormalization())
  model.add(tf.keras.layers.LSTM(70, return_sequences = True))
  #model.add(tf.keras.layers.BatchNormalization())
  #model.add(tf.keras.layers.LSTM(100, return_sequences = True))
  model.add(tf.keras.layers.Dropout(0.2))
  model.add(tf.keras.layers.LSTM(50))
  #model.add(tf.keras.layers.Dense(8, activation = 'relu'))
  ##model.add(tf.keras.layers.Dense(11, activation = 'linear'))
  model.add(tf.keras.layers.Dropout(0.2))
  model.add(tf.keras.layers.Dense(11, activation = 'linear'))

  model.summary()
  """


import json
import sys

import aes_functions
import rsa_functions
from exceptions.Exceptions import IncorrectData
from socket_class import SOCKET_SIMPLE_TCP

def receiveAESMessage(s):
    return s.receive(), s.receive(), s.receive()

def checkMessageGCM(key, iv, cif, mac):
    res = aes_functions.decipherAES_GCM(key, iv, cif, mac)
    if res is not False:
        return res
    else:
        print("AIUDAAAA :(")
        print("Corrupted Message")

def sendAESMessage(socket, criptograma, mac, nonce):
    socket.send(criptograma)
    socket.send(mac)
    socket.send(nonce)

def bob_socket(port):
    return SOCKET_SIMPLE_TCP('127.0.0.1', port)

class Bob:
    def __init__(self):
        self.name = "Bob"
        self.port = 5552
        self.PK_BOB = rsa_functions.create_RSAKey()
        self.KBT = aes_functions.create_AESKey()
        self.KPT = rsa_functions.load_RSAKey_Public("TTP.pub")

    def savePK(self):
        return rsa_functions.save_RSAKey_Public("Bob.pub", self.PK_BOB)

if __name__ == '__main__':
    """--STEP 0--"""
    bob = Bob()
    bob.savePK()
    print(bob.PK_BOB.public_key().export_key())

    try:
        socket = bob_socket(bob.port)
        socket.connect()
    except Exception as e:
        sys.exit(f"An error occurred creating the socket with TTP: {e}")

    """--STEP 2--"""
    print("Establishing a connection with TTP...")
    try:
        engineKAT = aes_functions.startAES_GCM(bob.KBT)

        print("Sending data to TTP...")
        message = [bob.name, bob.KBT.hex()]
        json_AT = json.dumps(message)

        print("Message B -> T (decryption): " + json_AT)

        # Encrypt data
        encrypted_message = rsa_functions.cipherRSA_OAEP(json_AT.encode("utf-8"), bob.KPT.public_key())
        encrypted_signature = rsa_functions.signatureRSA_PSS(bob.KBT.hex().encode("utf-8"), bob.PK_BOB)

        # Send encrypted data
        socket.send(encrypted_message)
        socket.send(encrypted_signature)
    except Exception as e:
        socket.close()
        sys.exit(f"An error occurred in step 2: {e}")
    finally:
        print("END STEP 2")
        input("Press any key to continue")

    """--Step 5--"""
    try:
        socket = bob_socket(5555)
        socket.listen()
    except Exception as e:
        sys.exit(f"An error occurred creating the socket with Alice: {e}")

    try:
        print("Waiting for Alice...")
        msg = socket.receive()
        cipher_BT, mac_BT, iv_BT, cif_AB, mc_AB, iv_AB = json.loads(msg)

        decrypted_message = checkMessageGCM(bob.KBT, bytes.fromhex(iv_BT), bytes.fromhex(cipher_BT),
                                            bytes.fromhex(mac_BT))
        TS, KAB = json.loads(decrypted_message.decode('utf-8'))

        KAB = bytearray.fromhex(KAB)

        decrypted_message = checkMessageGCM(KAB, bytes.fromhex(iv_AB), bytes.fromhex(cif_AB),
                                            bytes.fromhex(mc_AB))
        sessionName, aux = json.loads(decrypted_message)

        if sessionName != 'Alice' and aux != TS:
            raise IncorrectData("Possible data modification  during communication")
        else:
            print("Reliable data, continued")
    except Exception as e:
        socket.close()
        sys.exit(f"An error occurred in step 5: {e}")
    finally:
        print("END STEP 5")
        input("Press any key to continue")

    """--Step 6--"""
    try:
        resolution = float(TS) + 1

        engineKAB = aes_functions.startAES_GCM(KAB)
        cif, mac, iv = aes_functions.cipherAES_GCM(engineKAB, str(resolution).encode("utf-8"))
        sendAESMessage(socket, cif, mac, iv)
    except Exception as e:
        socket.close()
        sys.exit(f"An error occurred in step 6: {e}")
    finally:
        print("END STEP 6")
        input("Press any key to continue")

    """--Step 7--"""
    try:
        print("Waiting for Alice")
        cif, mac, iv = receiveAESMessage(socket)
        textoClaro = checkMessageGCM(KAB, iv, cif, mac)
        msg = textoClaro.decode("utf-8")
        print("Message ->" + msg)
    except Exception as e:
        socket.close()
        sys.exit(f"An error occurred in step 7: {e}")
    finally:
        print("END STEP 7")
        input("Press any key to continue")

    """--Step 8--"""
    try:
        msg = "Hello Word!"
        engineKAB = aes_functions.startAES_GCM(KAB)
        cif, mac, iv = aes_functions.cipherAES_GCM(engineKAB, msg.encode("utf-8"))
        sendAESMessage(socket, cif, mac, iv)
    except Exception as e:
        socket.close()
        sys.exit(f"An error occurred in step 8: {e}")
    finally:
        print("END STEP 8")


from django import forms
from django.core.exceptions import ValidationError
from arcana_app.models import Driver, Truck, Trailer, Insurance, Freight

class DateInput(forms.DateInput):
    input_type = 'date'

class TimeInput(forms.TimeInput):
    input_type = 'time'

# class CheckboxInput(forms.CheckboxInput):
#     input_type = 'checkbox'

class AddDriverForm(forms.ModelForm):
    class Meta:
        model = Driver
        fields = '__all__'
        widgets = {
            'birth_date': DateInput(),
        }

    def __init__(self, *args, **kwargs):
        super(AddDriverForm, self).__init__(*args, **kwargs)
        for visible in self.visible_fields():
            visible.field.widget.attrs['class'] = 'form-control'

class AddTruckForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(AddTruckForm, self).__init__(*args, **kwargs)
        for visible in self.visible_fields():
            visible.field.widget.attrs['class'] = 'form-control'

    class Meta:
        model = Truck
        fields = '__all__'
        widgets = {
            'begin_MOT': DateInput(),
            'expire_MOT': DateInput(),

        }

        # widgets = {
        #     'has_actual_MOT': forms.CheckboxInput(
        #         attrs={'class': 'required checkbox form-select', 'disabled': 'disabled or true'}),
        # }

class AddTrailerForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(AddTrailerForm, self).__init__(*args, **kwargs)
        for visible in self.visible_fields():
            visible.field.widget.attrs['class'] = 'form-control'

    class Meta:
        model = Trailer
        fields = '__all__'
        widgets = {
            'begin_MOT': DateInput(),
            'expire_MOT': DateInput(),
        }

class AddInsuranceForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(AddInsuranceForm, self).__init__(*args, **kwargs)
        for visible in self.visible_fields():
            visible.field.widget.attrs['class'] = 'form-control'

    class Meta:
        model = Insurance
        fields = '__all__'

    def clean(self):
        data = super().clean()
        if not data['begin_date'] <= data['end_date']:
            raise ValidationError("Begin date can't be earlier than end date!")
        return data

class AddFreightForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(AddFreightForm, self).__init__(*args, **kwargs)
        for visible in self.visible_fields():
            visible.field.widget.attrs['class'] = 'form-control'

    class Meta:
        model = Freight
        fields = '__all__'
        widgets = {
            'date_of_loading': DateInput(),
            'date_of_unloading': DateInput(),
            'hour_of_loading': TimeInput(),
            'hour_of_unloading': TimeInput(),
        }


from __future__ import print_function
import requests, lxml.html

headers = {'user-agent': 'taco'}
urls_to_check = [
    'http://www.packtpub.com/application-development/python-data-structures-and-algorithm',
    'https://www.packtpub.com/big-data-and-business-intelligence/learning-data-mining-python-second-edition',
    'https://www.packtpub.com/big-data-and-business-intelligence/neural-network-programming-python',
    'https://www.packtpub.com/application-development/python-programming-blueprints'
                ]
print()
for url in urls_to_check:
    title = url.split('/')[-1].replace('-', ' ').title()
    print('Checking for title: %s'%title)
    page = requests.get(url, headers=headers).content
    tree = lxml.html.fromstring(page)
    if not tree.cssselect('.title-preorder') and not tree.cssselect('.alpha-text'):
        print('\t\n%s [READY FOR DOWNLOAD]\n'%title)
    else:
        print('\t\t\t\t\t\t\t(negative)')

url = 'https://www.packtpub.com/packt/offers/free-learning'
print('Checking the [FREE] title...')
page = requests.get(url, headers=headers).content
tree = lxml.html.fromstring(page)
print('\n\tFree Book: %s\n'%tree.cssselect('.dotd-title h2')[0].text_content().strip())


import unittest
import json
from django.test import TestCase
from datetime import datetime
from utente.models import Utente, Prodotto, ProdottoCarrello, Carrello, Pagamento, Ordine
from vetrine.models import Vetrina, VetrinaAmministratore, ResocontoVendite

# test della creazione di un utente e verifica del relativo carrello associato #test ok
class UtenteTest(TestCase):
    def test_save_creates_carrello(self):
        utente = Utente.objects.create(username='testuser', email='test@example.com')
        carrello = Carrello.objects.get(possessore=utente)
        self.assertEqual(carrello.possessore, utente)

# test creazione di un prodotto e verifica della quantità #test ok

class ProdottoTest(TestCase):
    def setUp(self):
        self.prodotto = Prodotto.objects.create(
            nome='Prodotto di test',
            codice_seriale=12345,
            tipologia='Test',
            descrizione='Descrizione di test',
            prezzo=9.99,
            disponibilita=10
        )

    def test_creazione_prodotto(self):
        self.assertEqual(self.prodotto.nome, 'Prodotto di test')
        self.assertEqual(self.prodotto.codice_seriale, 12345)
        self.assertEqual(self.prodotto.tipologia, 'Test')
        self.assertEqual(self.prodotto.descrizione, 'Descrizione di test')
        self.assertEqual(self.prodotto.prezzo, 9.99)
        self.assertEqual(self.prodotto.disponibilita, 10)

    def test_aggiunta_quantita_venduta(self):
        self.assertEqual(self.prodotto.pezzi_venduti, 0)
        self.prodotto.pezzi_venduti = 5
        self.assertEqual(self.prodotto.pezzi_venduti, 5)

    def test_riduzione_disponibilita(self):
        self.assertEqual(self.prodotto.disponibilita, 10)
        self.prodotto.disponibilita -= 3
        self.assertEqual(self.prodotto.disponibilita, 7)

    def test_guadagno_totale(self):
        self.assertEqual(self.prodotto.guadagno_totale, 0)
        self.prodotto.pezzi_venduti = 5
        self.assertEqual(self.prodotto.guadagno_totale, 49.95)  # 5 * 9.99

    def tearDown(self):
        self.prodotto.delete()

# test di aggiunta di un prodotto al carrello #test ok
class ProdottoCarrelloTest(TestCase):
    def test_str_method(self):
        utente = Utente.objects.create(username='testuser', email='test@example.com')
        vetrina = Vetrina.objects.create(ID_vetrina='Test Vetrina')
        resoconto = ResocontoVendite.objects.create(ID_resoconto='Test Resoconto')
        prodotto = Prodotto.objects.create(
            nome='Test Prodotto',
            codice_seriale=1,
            vetrina=vetrina,
            resoconto_vendite=resoconto
        )
        prodotto_carrello = ProdottoCarrello.objects.create(utente=utente, prodotto=prodotto)
        self.assertEqual(str(prodotto_carrello), str(prodotto))

# test creazione di un carrello
class CarrelloTest(TestCase): #test ok
    def test_str_method(self):
        utente = Utente.objects.create(username='testuser', email='test@example.com')
        carrello, _ = Carrello.objects.get_or_create(possessore=utente)
        self.assertEqual(carrello.__str__(), 'testuser')

# test impostazione e verifica del pagamento
class PagamentoTest(TestCase): #test ok
    def test_str_method(self):
        pagamento = Pagamento.objects.create(numero_carta=1234567890)
        self.assertEqual(pagamento.numero_carta, 1234567890)

# test di creazione di un ordine #test ok
class OrdineTest(TestCase):
    def test_str_method(self):
        ordine, _ = Ordine.objects.get_or_create(
            numero_ordine='1',
            carrello=json.dumps([]),
            data_ordine=datetime.now(),
            numero_carta='1234567890'  # Fornisci un numero di carta valido qui
        )
        self.assertEqual(ordine.numero_ordine, '1')

if __name__ == '__main__':
    unittest.main()


import os.path
from flask import Flask
from flaskext.sqlalchemy import SQLAlchemy

CONFIG_FILEPATH = os.path.join(os.path.dirname(__file__), "../config.cfg")

def auto_register_modules(app):
    """Registers modules from :mod:`subleekr` to application."""
    import subleekr
    for modname in subleekr.__modules__:
        __import__("{0}.{1}".format(subleekr.__name__, modname))
        module = getattr(subleekr, modname)
        module.app.super_app = app
        app.register_module(module.app)

def create_app(__name__=__name__):
    app = Flask(__name__)
    try:
        app.config.from_pyfile(CONFIG_FILEPATH)
    except IOError:
        pass
    auto_register_modules(app)
    app.db = SQLAlchemy(app)
    return app


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def rightSideView(self, root: Optional[TreeNode]) -> List[int]:
        height = 0
        subtree = root
        def height(subtree):
            if not subtree :
                return 0
            return max(height(subtree.left), height(subtree.right))+1
        tree_height = height(root)
        result =[-1 for x in range(tree_height)]
        import collections
        q = collections.deque()
        q.append((root, 0))
        while q:
            x, level = q.popleft()
            if not x:
                continue
            if x.left:
                q.append((x.left,level+1))
            if x.right:
                q.append((x.right, level+1))
            result[level] = x.val
        return result

Leetcode/right side view of binary tree.py


# Iris Recognition
# 04. Module to match iris descriptions.
# Language: Python 3

import numpy
import cv2

ROTATIONS = [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

def _rotate_norm_image(image, rotation):
    output = numpy.zeros(image.shape, image.dtype)

    if rotation == 0:
        return image

    else:
        output[:, rotation:] = image[:, :-rotation]
        output[:, :rotation] = image[:, -rotation:]

    return output

def _compute_norm_hamming_distance(description_1, mask_1, description2, mask_2):
    comb_mask = cv2.bitwise_and(mask_1, mask_2)

    bit_up_count = numpy.sum(comb_mask > 0)

    xor_output = cv2.bitwise_xor(description_1, description2)
    xor_output = cv2.bitwise_and(xor_output, xor_output, mask=comb_mask)
    dist = numpy.sum(xor_output > 0)

    return float(dist) / bit_up_count

def match(descriptions_1, mask_1, descriptions_2, mask_2):
    rot_distances = []

    for rotation in ROTATIONS:
        distances = []

        for i in range(len(descriptions_1)):  # could be "for i in range(len(descriptions_2)):"
            desc_1 = descriptions_1[i]
            rot_desc_2 = _rotate_norm_image(descriptions_2[i], rotation)
            rot_mask_2 = _rotate_norm_image(mask_2, rotation)

            distances.append(_compute_norm_hamming_distance(desc_1, mask_1, rot_desc_2, rot_mask_2))

        rot_distances.append(numpy.mean(distances))

    print('[INFO] Computed normalized Hamming distance.')
    return numpy.min(rot_distances)


#!/usr/bin/env python3.7

import argparse
import json
import sys

def matches(parts, subject):
    if len(parts) == 0:
        yield subject
        return

    part, *rest = parts

    # If we're extracting something from `subject`, and `subject` is neither a
    # list nor a dict, then there's nothing to extract.  Whether this is an
    # error or just a no-op was part of how my original solution was wrong.
    if type(subject) not in [list, dict]:
        return

    if type(subject) is list:
        if part == '*':
            for child in subject:
                yield from matches(rest, child)
            return

        try:
            index = int(part)
        except ValueError:
            return  # can't extract a property name from a list

        yield from matches(rest, subject[index])
    else:
        assert type(subject) is dict

        if part == '*':
            for child in subject.values():
                yield from matches(rest, child)
        elif part in subject:
            yield from matches(rest, subject[part])

def parse(pattern):
    # Corner case:  If the pattern is empty, then splitting on "." would yield
    # `[""]` instead of `[]`.
    if len(pattern) == 0:
        return []
    else:
        return pattern.split('.')

def extract(pattern, subject):
    parts = parse(pattern)
    results = list(matches(parts, subject))

    # If there were no wildcards in the query, then at most one thing can be
    # matched.  Avoid the redundant outer list when possible.
    if '*' in parts:
        return results  # list of results

    if len(results) == 0:
        return None

    assert len(results) == 1
    return results[0]

def parse_command_line(args):
    parser = argparse.ArgumentParser(description='Extract values from JSON.')

    parser.add_argument('pattern',
                        help='JSON query (path) to extract from input')

    return parser.parse_args()

if __name__ == '__main__':
    options = parse_command_line(sys.argv[1:])
    result = extract(options.pattern, json.load(sys.stdin))

    if result is not None:
        json.dump(result, sys.stdout, indent=4, sort_keys=True)

    print()  # for the newline


import datetime
import pandas as pd

from helper.fetch import Fetch
from helper.dynamic_scrape import DynamicScrape
from helper.property_helper import PropertyHelper

class Dhalia(object):
    source = 'Dhalia'

    columns = [
        'Reference', 'Town', 'Type', 'Stage',
        'Bedrooms', 'Bathrooms',
        'TotalSqm', 'IntArea', 'ExtArea', 'Price'
    ]

    @staticmethod
    def fetch_data(is_sale: bool) -> pd.DataFrame:
        data = pd.DataFrame()
        proxies = Fetch.load_proxies()

        page_type = 'buy' if is_sale else 'rent'
        page_element = f'//div[@class="searchForm searchForm--quick-search page-{page_type}"]'
        driver = Fetch.get_dynamic(f'https://www.dhalia.com/{page_type}/?pageIndex=1', proxies, page_element, True)

        x_pages = '//li[@class="pager__last"]/a'
        DynamicScrape.await_element(driver, x_pages)
        pages = int(DynamicScrape.get_link(driver, x_pages).split('=')[1])

        for page in range(1, pages+1):
            x_links = '//a[@class="propertybox"]'
            links = DynamicScrape.get_links(driver, x_links)

            listing = []

            x_features = './/div[@class="property-top__col__part property-top__col__part--others"]/span'
            x_type_town = './/div[@class="property-top__col"]/h1'
            x_description = './/div[@class="description write-up"]'
            x_price = './/div[@class="property-top__col__part property-top__col__part--price"]'

            for i, link in enumerate(links):
                page_element = '//section[@class="property-detail-wrapper"]'
                successful = DynamicScrape.open_tab_link(driver, link, page_element)

                if successful:
                    features = DynamicScrape.get_texts(driver, x_features)

                    reference = [feature for feature in features if 'Ref: ' in feature]
                    reference = reference[0].replace('Ref: ', '').strip() if len(reference) else None

                    type_town = DynamicScrape.get_text(driver, x_type_town)

                    town = type_town.split(' in ')[1].strip()
                    type = type_town.split(' in ')[0].strip()

                    stage = PropertyHelper.determine_stage(driver, x_description, is_sale)

                    bedrooms = [side_info for side_info in features if 'Bedrooms' in side_info]
                    bedrooms = bedrooms[0].replace('Bedrooms', '') if len(bedrooms) else None

                    bathrooms = [side_info for side_info in features if 'Bathrooms' in side_info]
                    bathrooms = bathrooms[0].replace('Bathrooms', '') if len(bathrooms) else None

                    area = [side_info for side_info in features if 'm²' in side_info]
                    area = area[0].replace('m²', '').split('/') if len(area) else None

                    total_sqm = area[0] if area else None
                    int_area = area[1] if area else None
                    ext_area = area[2] if area else None

                    price = DynamicScrape.get_text(driver, x_price)
                    price = price.replace('€', '').replace(',', '')

                    try:
                        if ' daily' in price:
                            price = int(price.replace(' daily', '')) * 30
                        elif ' monthly' in price:
                            price = int(price.replace(' monthly', ''))
                        elif ' yearly' in price:
                            price = round(int(price.replace(' yearly', '')) / 12)
                    except ValueError:
                        price = None

                    listing.append([
                        reference, town, type, stage,
                        bedrooms, bathrooms,
                        total_sqm, int_area, ext_area, price
                    ])

                DynamicScrape.close_tab_link(driver)

                print(
                    '%s\t %s\t Page %03d of %03d\t Entry %03d of %03d' %
                    (datetime.datetime.now().strftime("%d-%m-%Y %H:%M:%S"), Dhalia.source + ' ' + page_type.title(), page, pages, i+1, len(links))
                )

            # Concatenate previous data frame with data of current page
            page_data = pd.DataFrame(listing, columns=Dhalia.columns)
            data = pd.concat([data, page_data])

            # Click Next Page
            x_next_page = f'//ul[@class="pager"]/li/a/span[text()="{page+1}"]'
            x_await_page = f'//ul[@class="pager"]/li[@class="pager__current"]/a/span[text()="{page+1}"]'
            DynamicScrape.click_element(driver, x_next_page, x_await_page)

        # Add source and rename columns
        data.insert(0, 'Is_Sale', is_sale)
        data.insert(1, 'Source', Dhalia.source)

        # Close Driver
        Fetch.dynamic_close_browser(driver)

        # Return the data
        return data

    @staticmethod
    def fetch_res_sale():
        return Dhalia.fetch_data(True)

    @staticmethod
    def fetch_res_rent():
        return Dhalia.fetch_data(False)

    @staticmethod
    def fetch_all(file_path: str) -> None:
        # Fetching data
        res_sale = Dhalia.fetch_res_sale()
        res_rent = Dhalia.fetch_res_rent()

        # Concatenate Data
        data = pd.concat([res_sale, res_rent])

        # Save data frame to CSV file
        data.to_csv(file_path, index=False)


"""
Some of code was taken from https://pytorch.org/vision/stable/_modules/torchvision/models/resnet.html
"""

import torch
from torch import Tensor, nn
from typing import Optional, List
from torchvision.models import resnet18

def conv3x3(input_size: int, output_size: int, stride: int = 1) -> nn.Conv2d:
    return nn.Conv2d(input_size, output_size, kernel_size=3, stride=stride, padding=1, bias=False)

def conv1x1(input_size: int, output_size: int, stride: int = 1) -> nn.Conv2d:
    return nn.Conv2d(input_size, output_size, kernel_size=1, stride=stride, bias=False)

class BasicBlock(nn.Module):
    def __init__(
        self,
        input_size: int,
        output_size: int,
        stride: int = 1,
        downsample: Optional[nn.Module] = None,
    ):
        super().__init__()

        self.conv1 = conv3x3(input_size, output_size, stride)
        self.bn1 = nn.BatchNorm2d(output_size)
        self.relu = nn.ReLU(inplace=True)
        self.conv2 = conv3x3(output_size, output_size)
        self.bn2 = nn.BatchNorm2d(output_size)
        self.downsample = downsample
        self.stride = stride

    def forward(self, x: Tensor) -> Tensor:
        identity = x

        out = self.conv1(x)
        out = self.bn1(out)
        out = self.relu(out)

        out = self.conv2(out)
        out = self.bn2(out)

        if self.downsample is not None:
            identity = self.downsample(x)

        out += identity
        out = self.relu(out)

        return out

class ResNetCNN(nn.Module):
    """
    Realizes ResNet-like neural network for one-dimentional pictures.
    """

    def __init__(
        self,
        layers: List[int] = None,
        output_size: int = 128,
    ):
        super().__init__()

        if layers is None:
            layers = [2, 2, 2]
        if len(layers) != 3:
            raise ValueError(
                f'List of layers should have 3 elements, got {len(layers)}')

        self.relu = nn.ReLU()
        self.output = output_size
        self.input_size = 128
        self.layer0 = nn.Sequential(
            nn.Conv2d(1, self.input_size, kernel_size=7, padding=3),
            nn.BatchNorm2d(self.input_size),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )
        self.layer1 = self._make_layer(128, layers[0])
        self.layer2 = self._make_layer(256, layers[1], stride=2)
        self.layer3 = self._make_layer(512, layers[2], stride=2)
        self.downsample = conv1x1(512, self.output)

    def _make_layer(self, output_size: int, blocks: int, stride: int = 1) -> nn.Sequential:
        downsample = None
        if stride != 1 or self.input_size != output_size:
            downsample = nn.Sequential(
                conv1x1(self.input_size, output_size, stride),
                nn.BatchNorm2d(output_size),
            )
        layers = [BasicBlock(self.input_size, output_size, stride, downsample)]

        self.input_size = output_size

        for _ in range(1, blocks):
            layers.append(BasicBlock(self.input_size, output_size))

        return nn.Sequential(*layers)

    def forward(self, x: Tensor) -> Tensor:
        x = self.layer0(x)
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        # (batch_size, output_channels, height, width)
        x = self.downsample(x)
        return x.squeeze(0)  # (output_channels, height, width)

class CNN(nn.Module):

    def __init__(self, output_size: int = 128):
        super().__init__()

        self.input_size = 64
        self.layer0 = nn.Sequential(
            nn.Conv2d(1, 64, kernel_size=7, padding=3),
            nn.BatchNorm2d(64),
            nn.ReLU(),
            nn.MaxPool2d((1, 2))
        )
        self.layer1 = self._make_layer(128)
        self.layer2 = self._make_layer(256)
        self.layer3 = self._make_layer(512)
        self.downsample = nn.Sequential(
            conv3x3(self.input_size, output_size),
            nn.BatchNorm2d(output_size),
            nn.ReLU()
        )

    def forward(self, x: Tensor) -> Tensor:
        x = self.layer0(x)
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.downsample(x)
        return x.squeeze(0)

    def _make_layer(self, output_size: int) -> nn.Sequential:
        layer = nn.Sequential(
            conv3x3(self.input_size, output_size),
            nn.BatchNorm2d(output_size),
            nn.ReLU(),
            conv3x3(output_size, output_size),
            nn.BatchNorm2d(output_size),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )
        self.input_size = output_size
        return layer


from django.contrib.auth.decorators import permission_required , login_required
from django.shortcuts import render , redirect , get_object_or_404,HttpResponseRedirect , HttpResponse

from form_1.forms import Form1Form
from form_1.models import Form1
from giris.views import login_view
from .models import Form3 as Form3Model , Form3 , Malzeme
from .forms import Form3Form , MalzemeForm
from django.db.models import Q
import mimetypes
from form2.models import Form2
from form4.models import Form4

@login_required(login_url=login_view)
# Create your views here.
def form3_view(request):
    if request.user.is_staff or request.user.is_superuser:
        listem = Form3Model.objects.all().order_by('Form33__id')
    else:
        listem = Form3Model.objects.all().order_by('Form33__id').filter(Olusturan=request.user)

    """query = request.GET.get('q')
    if query:
        listem = listem.filter(
            Q(id=int(query)) |
            Q(Olusturan__username__icontains=query) |
            Q(isin_kategorisi__icontains=query) |
            Q(Aciklama__icontains=query)
        ).distinct()"""
    return render(request , 'Form3/Form3.html' , {'listem': listem,'islemde':
                                                  [islemde.Form44 for islemde in Form4.objects.all() if islemde.Form44]

                                                 ,'malzeme':malzeme })

@login_required(login_url=login_view)
def create(request,form1):
    form3=Form3Form(request.POST or None, request.FILES or None)

    context = {'form3': form3}
    if request.method == "POST":
        if form3.is_valid():
            a=form3.save(commit=False)
            a.Form33 = Form2.objects.get(Form22=form1)
            a.Olusturan = request.user
            a.save()
            if a.isin_kategorisi=='Malz.Tedariği':
                return redirect('create_malzeme',form3=a.id)
        return redirect(form3_view)
    return render(request, 'Form3/create.html', context)

@login_required(login_url=login_view)
def detail(request,pk):
    listem = get_object_or_404(Form3Model, id=pk)
    context = {'listem': listem}
    return render(request , 'Form3/detail.html', context)

@login_required(login_url=login_view)
@permission_required('form3.delete_form3',login_url=form3_view)
def delete(request , pk):
    listem = Form3Model.objects.get(id=pk)
    listem.delete()
    context = {'listem': listem}
    return redirect('form3_view')

@login_required(login_url=login_view)
@permission_required('form3.change_form3',login_url=form3_view)
def update(request,pk):
    listem = get_object_or_404(Form3Model , id=pk)
    form3 = Form3Form(request.POST or None ,request.FILES or None, instance=listem)
    if form3.is_valid():
        form3.save()
        return redirect('form3_view')
    context = {'form3': form3}
    return render(request, 'Form3/create.html', context)

@login_required(login_url=login_view)
def download(request , pk):
    listem = get_object_or_404(Form3Model , id=pk)
    file_path = listem.dosya.path
    file_name = str(listem.dosya)

    fh = open(file_path , 'rb')
    mime_type , _ = mimetypes.guess_type(file_path)
    response = HttpResponse(fh , content_type=mime_type)
    response['Content-Disposition'] = f"attachment; filename={file_name}"
    return response

@login_required(login_url=login_view)
def create_malzeme(request,form3):
    malzeme_tedarik=MalzemeForm(request.POST or None)
    context={'malzeme_tedarik':malzeme_tedarik}
    if request.method=='POST' and malzeme_tedarik.is_valid():
        b=malzeme_tedarik.save(commit=False)
        b.Form333=Form3.objects.get(id=form3)
        b.save()
    return render(request,'Form3/MalzemeTedarik.html',context)

@login_required(login_url=login_view)
def malzeme(request,form3):
    malzemeler=Malzeme.objects.filter(Form333=form3)
    context={'malzemeler':malzemeler}
    return render(request,'Form3/malzemeview.html',context)


import os,sys,shutil,multiprocessing
sys.path.append("..")
from base.get_config import MyConfig as myconfig
pid=multiprocessing.current_process().pid#获取pid进程编号
folderpath=myconfig("project","project_path").value+myconfig("project","data_path").value

def folder_create(path=None):
	if path:
		path=path
	else:
		path=folderpath+"/"+"testsuite-pid-"+str(pid)

	if os.path.exists(path)==False:
		os.mkdir(path)
	return path

def folder_clear(path=folderpath):
	path=os.path.abspath(path)#转换为绝对路径
	#print("目录名称",os.path.dirname(path))
	if path.split("\\")[len(path.split("\\"))-1]=="runningdata":#如果是runningdata目录，name操作删除
		for root,dirs,filename in os.walk(path,False):
			#print("-------------------------------------------------")
			#print(str(root),"||",str(dirs)+"||"+str(filename))
			for dir in dirs:
				if dir!="data_debug" and dir!="data_running" and root==path:
					shutil.rmtree(path+"/"+dir)
	else:
		print("清空目录:"+str(path)+"下文件夹，谨慎操作！")

if __name__=="__main__":
	print("创建了文件：",folder_create())
	print(folder_clear())


from django.urls import path
from home import views

urlpatterns = [
    path('sign', views.sign, name='sign'),
    path('', views.loginp, name='loginp'),
    path('logoutp', views.logoutp, name='logoutp'),
    path('base', views.base, name='base'),
    path('mainhome', views.mainhome, name='home'),
    # path('accounts/login/', views.predict_demand_supply_dtree, name='predict'),
    path('predict/', views.predict_demand_supply_dtree, name='predict'),
    path('prediction_results', views.predict_demand_supply_dtree, name='predictResult'),
    path('pcw', views.pcw, name='pcw'),
    path('prediction_results2', views.pcw, name='predictResult2'),
    path('pcacw', views.pcacw, name='pcacw'),
    path('prediction_results3', views.pcacw, name='predictResult3')
]


import sys, time, itertools

import dill as pickle

import numpy as np
import matplotlib.pyplot as plt

import scipy.interpolate as interp
import scipy.stats as stats
import scipy.optimize as opti

import bead_util as bu
import calib_util as cal
import transfer_func_util as tf
import configuration as config

import warnings
warnings.filterwarnings("ignore")

##################################################################
######################## Script Params ###########################

only_closest = False #True
minsep = 15       # um
maxthrow = 80     # um
beadheight = 10   # um

#data_dir = '/data/20180314/bead1/grav_data/ydrive_1sep_1height_extdrive_nofield_long'
#data_dir = '/data/20180314/bead1/grav_data/ydrive_1sep_1height_nofield_shieldin'
#data_dir = '/data/20180314/bead1/grav_data/ydrive_1sep_1height_1V-1300Hz_shieldin_0mV-cant'
#data_dir = '/data/20180314/bead1/grav_data/ydrive_1sep_1height_2V-2200Hz_shield_0mV-cant'

data_dir = '/data/20180314/bead1/grav_data/ydrive_6sep_1height_shield-2Vac-2200Hz_cant-0mV'

#savepath = '/sensitivities/20180314_grav_shield-2200Hz_cant-m100mV_allharm.npy'
savepath = '/sensitivities/20180314_grav_shieldin-2V-2200Hz_cant-0V_allharm.npy'
save = False
load = False
file_inds = (0, 10)

theory_data_dir = '/data/grav_sim_data/2um_spacing_data/'

tfdate = '' #'20180215'
diag = False

confidence_level = 0.95

lamb_range = (1.7e-6, 1e-4)

#user_lims = [(65e-6, 80e-6), (-240e-6, 240e-6), (-5e-6, 5e-6)]
user_lims = [(5e-6, 80e-6), (-240e-6, 240e-6), (-5e-6, 5e-6)]
#user_lims = []

tophatf = 300   # Hz, doesn't reconstruct data above this frequency
nharmonics = 10
harms = [1,3,5,7]

plot_just_current = False
figtitle = ''

ignoreX = False
ignoreY = False
ignoreZ = False

compute_min_alpha = False

##################################################################
################# Constraints to plot against ####################

alpha_plot_lims = (1000, 10**13)
lambda_plot_lims = (10**(-7), 10**(-4))

#limitdata_path = '/home/charles/opt_lev_analysis/gravity_sim/gravity_sim_v1/data/' + \
#                 'decca2_limit.txt'

limitdata_path = '/sensitivities/decca1_limits.txt'
limitdata = np.loadtxt(limitdata_path, delimiter=',')
limitlab = 'No Decca 2'

#limitdata_path2 = '/home/charles/opt_lev_analysis/gravity_sim/gravity_sim_v1/data/' + \
#                 'no_decca2_limit.txt'
limitdata_path2 = '/sensitivities/decca2_limits.txt'
limitdata2 = np.loadtxt(limitdata_path2, delimiter=',')
limitlab2 = 'With Decca 2'

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

# Various fitting functions
def parabola(x, a, b, c):
    return a * x**2 + b * x + c

def line(x, a, b):
    return a * x + b

def const(x, a):
    return a

def flicker(x, a):
    return a * (1. / x)

def build_mod_grav_funcs(theory_data_dir):
    '''Loads data from the output of /data/grav_sim_data/process_data.py
       which processes the raw simulation output from the farmshare code

       INPUTS: theory_data_dir, path to the directory containing the data

       OUTPUTS: gfuncs, 3 element list with 3D interpolating functions
                        for regular gravity [fx, fy, fz]
                yukfuncs, 3 x Nlambda array with 3D interpolating function
                          for modified gravity with indexing:
                          [[y0_fx, y1_fx, ...], [y0_fy, ...], [y0_fz, ...]]
                lambdas, np.array with all lambdas from the simulation
                lims, 3 element with tuples for (min, max) of coordinate
                      limits in interpolation
    '''

    # Load modified gravity curves from simulation output
    Gdata = np.load(theory_data_dir + 'Gravdata.npy')
    yukdata = np.load(theory_data_dir + 'yukdata.npy')
    lambdas = np.load(theory_data_dir + 'lambdas.npy')
    xpos = np.load(theory_data_dir + 'xpos.npy')
    ypos = np.load(theory_data_dir + 'ypos.npy')
    zpos = np.load(theory_data_dir + 'zpos.npy')

    if lambdas[-1] > lambdas[0]:
        lambdas = lambdas[::-1]
        yukdata = np.flip(yukdata, 0)

    # Find limits to avoid out of range erros in interpolation
    xlim = (np.min(xpos), np.max(xpos))
    ylim = (np.min(ypos), np.max(ypos))
    zlim = (np.min(zpos), np.max(zpos))

    # Build interpolating functions for regular gravity
    gfuncs = [0,0,0]
    for resp in [0,1,2]:
        gfuncs[resp] = interp.RegularGridInterpolator((xpos, ypos, zpos), Gdata[:,:,:,resp])

    # Build interpolating functions for yukawa-modified gravity
    yukfuncs = [[],[],[]]
    for resp in [0,1,2]:
        for lambind, yuklambda in enumerate(lambdas):
            lamb_func = interp.RegularGridInterpolator((xpos, ypos, zpos), yukdata[lambind,:,:,:,resp])
            yukfuncs[resp].append(lamb_func)
    lims = [xlim, ylim, zlim]

    return gfuncs, yukfuncs, lambdas, lims

def get_data_at_harms(files, gfuncs, yukfuncs, lambdas, lims, \
                      minsep=20, maxthrow=80, beadheight=5,\
                      cantind=0, ax1='x', ax2='z', diag=True, plottf=False, \
                      width=0, nharmonics=10, harms=[], \
                      ext_cant_drive=False, ext_cant_ind=1, \
                      ignoreX=False, ignoreY=False, ignoreZ=False,  noiseband=10):
    '''Loops over a list of file names, loads each file, diagonalizes,
       then performs an optimal filter using the cantilever drive and
       a theoretical force vs position to generate the filter/template.
       The result of the optimal filtering is stored, and the data
       released from memory

       INPUTS: files, list of files names to extract data
               cantind, cantilever electrode index
               ax1, axis with different DC positions
               ax2, 2nd axis with different DC positions

       OUTPUTS:
    '''

    #parts = data_dir.split('/')
    #prefix = parts[-1]
    #savepath = '/processed_data/grav_data/' + prefix + '_fildat.p'
    #try:
    #    fildat = pickle.load(open(savepath, 'rb'))
    #    return fildat
    #except:
    #    print 'Loading data from: ', data_dir

    fildat = {}
    temp_gdat = {}
    for fil_ind, fil in enumerate(files):
        bu.progress_bar(fil_ind, len(files), suffix=' Sorting Files, Extracting Data')

        ### Load data
        df = bu.DataFile()
        df.load(fil)

        df.calibrate_stage_position()

        cantbias = df.electrode_settings['dc_settings'][0]
        ax1pos = df.stage_settings[ax1 + ' DC']
        ax2pos = df.stage_settings[ax2 + ' DC']

        if cantbias not in list(fildat.keys()):
            fildat[cantbias] = {}
        if ax1pos not in list(fildat[cantbias].keys()):
            fildat[cantbias][ax1pos] = {}
        if ax2pos not in list(fildat[cantbias][ax1pos].keys()):
            fildat[cantbias][ax1pos][ax2pos] = []

        if ax1pos not in list(temp_gdat.keys()):
            temp_gdat[ax1pos] = {}
        if ax2pos not in list(temp_gdat[ax1pos].keys()):
            temp_gdat[ax1pos][ax2pos] = [[], []]
            temp_gdat[ax1pos][ax2pos][1] = [[]] * len(lambdas)

        cfind = len(fildat[cantbias][ax1pos][ax2pos])
        fildat[cantbias][ax1pos][ax2pos].append([])

        if fil_ind == 0 and plottf:
            df.diagonalize(date=tfdate, maxfreq=tophatf, plot=True)
        else:
            df.diagonalize(date=tfdate, maxfreq=tophatf)

        if fil_ind == 0:
            ginds, fund_ind, drive_freq, drive_ind = \
                df.get_boolean_cantfilt(ext_cant_drive=ext_cant_drive, ext_cant_ind=ext_cant_ind, \
                                        nharmonics=nharmonics, harms=harms, width=width)

        datffts, diagdatffts, daterrs, diagdaterrs = \
                    df.get_datffts_and_errs(ginds, drive_freq, noiseband=noiseband, plot=False, \
                                            diag=diag)

        drivevec = df.cant_data[drive_ind]

        mindrive = np.min(drivevec)
        maxdrive = np.max(drivevec)

        posvec = np.linspace(mindrive, maxdrive, 500)
        ones = np.ones_like(posvec)

        start = time.time()
        for lambind, yuklambda in enumerate(lambdas):

            if ax1 == 'x' and ax2 == 'z':
                newxpos = minsep + (maxthrow - ax1pos)
                newheight = ax2pos - beadheight
            elif ax1 =='z' and ax2 == 'x':
                newxpos = minsep + (maxthrow - ax2pos)
                newheight = ax1pos - beadheight
            else:
                print("Coordinate axes don't make sense for gravity data...")
                print("Proceeding anyway, but results might be hard to interpret")
                newxpos = ax1pos
                newheight = ax2pos

            if (newxpos < lims[0][0]*1e6) or (newxpos > lims[0][1]*1e6):
                #print 'skipped x'
                continue

            if (newheight < lims[2][0]*1e6) or (newheight > lims[2][1]*1e6):
                #print 'skipped z'
                continue

            pts = np.stack((newxpos*ones, posvec, newheight*ones), axis=-1)

            gfft = [[], [], []]
            yukfft = [[], [], []]
            for resp in [0,1,2]:
                if (ignoreX and resp == 0) or (ignoreY and resp == 1) or (ignoreZ and resp == 2):
                    gfft[resp] = np.zeros(np.sum(ginds))
                    yukfft[resp] = np.zeros(np.sum(ginds))
                    continue

                if len(temp_gdat[ax1pos][ax2pos][0]):
                    gfft[resp] = temp_gdat[ax1pos][ax2pos][0][resp]
                else:
                    gforcevec = gfuncs[resp](pts*1e-6)
                    gforcefunc = interp.interp1d(posvec, gforcevec)
                    gforcet = gforcefunc(drivevec)

                    gfft[resp] =  np.fft.rfft(gforcet)[ginds]

                if len(temp_gdat[ax1pos][ax2pos][1][lambind]):
                    yukfft[resp] = temp_gdat[ax1pos][ax2pos][1][lambind][resp]
                else:
                    yukforcevec = yukfuncs[resp][lambind](pts*1e-6)
                    yukforcefunc = interp.interp1d(posvec, yukforcevec)
                    yukforcet = yukforcefunc(drivevec)

                    yukfft[resp] = np.fft.rfft(yukforcet)[ginds]

            gfft = np.array(gfft)
            yukfft = np.array(yukfft)

            temp_gdat[ax1pos][ax2pos][0] = gfft
            temp_gdat[ax1pos][ax2pos][1][lambind] = yukfft

            outdat = (yuklambda, datffts, diagdatffts, daterrs, diagdaterrs, gfft, yukfft)

            fildat[cantbias][ax1pos][ax2pos][cfind].append(outdat)

        stop = time.time()
        #print 'func eval time: ', stop-start

    return fildat

def get_alpha_lambda(fildat, diag=True, ignoreX=False, ignoreY=False, ignoreZ=False, \
                     plot=True, save=False, savepath='', confidence_level=0.95, \
                     only_closest=False, ax1='x', ax2='z', lamb_range=(1e-9, 1e-2)):
    '''Loops over a list of file names, loads each file, diagonalizes,
       then performs an optimal filter using the cantilever drive and
       a theoretical force vs position to generate the filter/template.
       The result of the optimal filtering is stored, and the data
       released from memory

       INPUTS: fildat

       OUTPUTS:
    '''

    # For the confidence interval, compute the inverse CDF of a
    # chi^2 distribution at given confidence level and compare to
    # liklihood ratio via a goodness of fit parameter.
    # Refer to scipy.stats documentation to understand chi2
    chi2dist = stats.chi2(1)
    # factor of 0.5 from Wilks's theorem: -2 log (Liklihood) ~ chi^2(1)
    con_val = 0.5 * chi2dist.ppf(confidence_level)

    colors = bu.get_color_map(len(lambdas))

    alphas = np.zeros_like(lambdas)
    diagalphas = np.zeros_like(lambdas)
    testalphas = np.linspace(-10**10, 10**10, 11)

    minalphas = [[]] * len(lambdas)

    biasvec = list(fildat.keys())
    biasvec.sort()
    ax1posvec = list(fildat[biasvec[0]].keys())
    ax1posvec.sort()
    ax2posvec = list(fildat[biasvec[0]][ax1posvec[0]].keys())
    ax2posvec.sort()

    if only_closest:
        if ax1 == 'x' and ax2 == 'z':
            seps = minsep + (maxthrow - np.array(ax1posvec))
            heights = np.array(ax2posvec) - beadheight
            sind = np.argmin(seps)
            hind = np.argmin(np.abs(heights - beadheight))
            ax1posvec = [ax1posvec[sind]]
            ax2posvec = [ax2posvec[hind]]

        elif ax1 =='z' and ax2 == 'x':
            seps = minsep + (maxthrow - np.array(ax2posvec))
            heights = np.array(ax1pos) - beadheight
            sind = np.argmin(seps)
            hind = np.argmin(np.abs(heights - beadheight))
            ax1posvec = [ax1posvec[hind]]
            ax2posvec = [ax2posvec[sind]]

    newlamb = lambdas[(lambdas > lamb_range[0]) * (lambdas < lamb_range[-1])]
    tot_iterations = len(biasvec) * len(ax1posvec) * len(ax2posvec) * \
                         len(newlamb) * len(testalphas) + 1
    i = -1

    # To test chi2 fit against "fake" data, uncomment these lines
    rands = np.random.randn(*fildat[biasvec[0]][ax1posvec[0]][ax2posvec[0]][0][0][1].shape)
    rands2 = np.random.randn(*fildat[biasvec[0]][ax1posvec[0]][ax2posvec[0]][0][0][1].shape)

    for lambind, yuklambda in enumerate(lambdas):
        #if lambind != 48:
        #    continue

        if (yuklambda < lamb_range[0]) or (yuklambda > lamb_range[1]):
            continue

        test = fildat[biasvec[0]][ax1posvec[0]][ax2posvec[0]][0][lambind]
        test_yukdat = test[-1]
        test_dat = test[1]

        newalpha = 1e-4 * np.sqrt(np.mean(np.abs(test_dat) / np.abs(test_yukdat)))
        testalphas = np.linspace(-1.0*newalpha, newalpha, 21)

        chi_sqs = np.zeros(len(testalphas))
        diagchi_sqs = np.zeros(len(testalphas))

        for alphaind, testalpha in enumerate(testalphas):
            N = 0
            chi_sq = 0
            diagchi_sq = 0

            for bias, ax1pos, ax2pos in itertools.product(biasvec, ax1posvec, ax2posvec):
                i += 1
                bu.progress_bar(i, tot_iterations, suffix=' Fitting the Data for Chi^2')

                for fil_ind in range(len(fildat[bias][ax1pos][ax2pos])):
                    dat = fildat[bias][ax1pos][ax2pos][fil_ind][lambind]
                    assert dat[0] == yuklambda
                    _, datfft, diagdatfft, daterr, diagdaterr, gfft, yukfft = dat

                    # To test chi2 fit against "fake" data, uncomment these lines
                    #datfft = yukfft * -0.5e9
                    #datfft += (1.0 / np.sqrt(2)) * daterr * rands + \
                    #          (1.0 / np.sqrt(2)) * daterr * rands2 * 1.0j
                    #gfft = np.zeros_like(datfft)

                    for resp in [0,1,2]:
                        if (ignoreX and resp == 0) or \
                           (ignoreY and resp == 1) or \
                           (ignoreZ and resp == 2):
                            print(ignoreX, ignoreY, ignoreZ, resp)
                            continue
                        re_diff = datfft[resp].real - \
                                  (gfft[resp].real + testalpha * yukfft[resp].real )
                        im_diff = datfft[resp].imag - \
                                  (gfft[resp].imag + testalpha * yukfft[resp].imag )
                        if diag:
                            diag_re_diff = diagdatfft[resp].real - \
                                           (gfft[resp].real + testalpha * yukfft[resp].real )
                            diag_im_diff = diagdatfft[resp].imag - \
                                           (gfft[resp].imag + testalpha * yukfft[resp].imag )

                        #plt.plot(np.abs(re_diff))
                        #plt.plot(daterr[resp])
                        #plt.show()

                        chi_sq += ( np.sum( np.abs(re_diff)**2 / (0.5*daterr[resp]**2) ) + \
                                  np.sum( np.abs(im_diff)**2 / (0.5*daterr[resp]**2) ) )
                        if diag:
                            diagchi_sq += ( np.sum( np.abs(diag_re_diff)**2 / \
                                                    (0.5*diagdaterr[resp]**2) ) + \
                                            np.sum( np.abs(diag_im_diff)**2 / \
                                                    (0.5*diagdaterr[resp]**2) ) )

                        N += len(re_diff) + len(im_diff)

            chi_sqs[alphaind] = chi_sq / (N - 1)
            if diag:
                diagchi_sqs[alphaind] = diagchi_sq / (N - 1)

        max_chi = np.max(chi_sqs)
        if diag:
            max_diagchi = np.max(diagchi_sqs)

        max_alpha = np.max(testalphas)

        p0 = [max_chi/max_alpha**2, 0, 1]
        if diag:
            diag_p0 = [max_diagchi/max_alpha**2, 0, 1]

        #if lambind == 0:
        #    p0 = [0.15e9, 0, 5]
        #else:
        #    p0 = p0_old

        if plot:
            plt.figure(1)
            plt.plot(testalphas, chi_sqs, color = colors[lambind])
            if diag:
                plt.figure(2)
                plt.plot(testalphas, diagchi_sqs, color = colors[lambind])

        try:
            popt, pcov = opti.curve_fit(parabola, testalphas, chi_sqs, \
                                            p0=p0, maxfev=100000)
            if diag:
                diagpopt, diagpcov = opti.curve_fit(parabola, testalphas, diagchi_sqs, \
                                                    p0=diag_p0, maxfev=1000000)
        except:
            print("Couldn't fit")
            popt = [0,0,0]
            popt[2] = np.mean(chi_sqs)

        regular_con_val = con_val + np.min(chi_sqs)
        if diag:
            diag_con_val = con_val + np.min(diagchi_sqs)

        # Select the positive root for the non-diagonalized data
        soln1 = ( -1.0 * popt[1] + np.sqrt( popt[1]**2 - \
                        4 * popt[0] * (popt[2] - regular_con_val)) ) / (2 * popt[0])
        soln2 = ( -1.0 * popt[1] - np.sqrt( popt[1]**2 - \
                        4 * popt[0] * (popt[2] - regular_con_val)) ) / (2 * popt[0])

        if diag:
            diagsoln1 = ( -1.0 * diagpopt[1] + np.sqrt( diagpopt[1]**2 - \
                            4 * diagpopt[0] * (diagpopt[2] - diag_con_val)) ) / (2 * diagpopt[0])
            diagsoln2 = ( -1.0 * diagpopt[1] - np.sqrt( diagpopt[1]**2 - \
                            4 * diagpopt[0] * (diagpopt[2] - diag_con_val)) ) / (2 * diagpopt[0])

        if soln1 > soln2:
            alpha_con = soln1
        else:
            alpha_con = soln2

        if diag:
            if diagsoln1 > diagsoln2:
                diagalpha_con = diagsoln1
            else:
                diagalpha_con = diagsoln2

        alphas[lambind] = alpha_con
        if diag:
            diagalphas[lambind] = alpha_con

    if plot:
        plt.figure(1)
        plt.title('Goodness of Fit for Various Lambda', fontsize=16)
        plt.xlabel('Alpha Parameter [arb]', fontsize=14)
        plt.ylabel('$\chi^2$', fontsize=18)

        if diag:
            plt.figure(2)
            plt.title('Goodness of Fit for Various Lambda - DIAG', fontsize=16)
            plt.xlabel('Alpha Parameter [arb]', fontsize=14)
            plt.ylabel('$\chi^2$', fontsize=18)

        plt.show()

    if not diag:
        diagalphas = np.zeros_like(alphas)

    if save:
        if savepath == '':
            print('No save path given, type full path here')
            savepath = input('path: ')

        np.save(savepath, [lambdas, alphas, diagalphas])

    return lambdas, alphas, diagalphas

def get_alpha_vs_file(fildat, diag=True, ignoreX=False, ignoreY=False, ignoreZ=False, \
                     plot=True, save=False, savepath='', confidence_level=0.95, \
                     only_closest=False, ax1='x', ax2='z', lamb_range=(1e-9, 1e-2)):
    '''Loops over a list of file names, loads each file, diagonalizes,
       then performs an optimal filter using the cantilever drive and
       a theoretical force vs position to generate the filter/template.
       The result of the optimal filtering is stored, and the data
       released from memory

       INPUTS: fildat

       OUTPUTS:
    '''

    # For the confidence interval, compute the inverse CDF of a
    # chi^2 distribution at given confidence level and compare to
    # liklihood ratio via a goodness of fit parameter.
    # Refer to scipy.stats documentation to understand chi2
    chi2dist = stats.chi2(1)
    # factor of 0.5 from Wilks's theorem: -2 log (Liklihood) ~ chi^2(1)
    con_val = 0.5 * chi2dist.ppf(confidence_level)

    colors = bu.get_color_map(len(lambdas))

    alphas = np.zeros_like(lambdas)
    diagalphas = np.zeros_like(lambdas)
    testalphas = np.linspace(-10**10, 10**10, 11)

    biasvec = list(fildat.keys())
    biasvec.sort()
    ax1posvec = list(fildat[biasvec[0]].keys())
    ax1posvec.sort()
    ax2posvec = list(fildat[biasvec[0]][ax1posvec[0]].keys())
    ax2posvec.sort()

    if only_closest:
        if ax1 == 'x' and ax2 == 'z':
            seps = minsep + (maxthrow - np.array(ax1posvec))
            heights = np.array(ax2posvec) - beadheight
            sind = np.argmin(seps)
            hind = np.argmin(np.abs(heights - beadheight))
            ax1posvec = [ax1posvec[sind]]
            ax2posvec = [ax2posvec[hind]]

        elif ax1 =='z' and ax2 == 'x':
            seps = minsep + (maxthrow - np.array(ax2posvec))
            heights = np.array(ax1pos) - beadheight
            sind = np.argmin(seps)
            hind = np.argmin(np.abs(heights - beadheight))
            ax1posvec = [ax1posvec[hind]]
            ax2posvec = [ax2posvec[sind]]

    newlamb = lambdas[(lambdas > lamb_range[0]) * (lambdas < lamb_range[-1])]
    tot_iterations = len(biasvec) * len(ax1posvec) * len(ax2posvec) * len(newlamb) * len(testalphas)
    i = -1

    for lambind, yuklambda in enumerate(lambdas):
        if lambind != 48:
            continue

        if (yuklambda < lamb_range[0]) or (yuklambda > lamb_range[1]):
            continue

        test = fildat[biasvec[0]][ax1posvec[0]][ax2posvec[0]][0][lambind]
        test_yukdat = test[-1]
        test_dat = test[1]

        newalpha = 1e-4 * np.sqrt(np.mean(np.abs(test_dat) / np.abs(test_yukdat)))
        testalphas = np.linspace(-1.0*newalpha, newalpha, 11)

        for bias, ax1pos, ax2pos in itertools.product(biasvec, ax1posvec, ax2posvec):
            i += 1
            bu.progress_bar(i, tot_iterations)

            minalphas = [0] * len(fildat[bias][ax1pos][ax2pos])
            diag_minalphas = [0] * len(fildat[bias][ax1pos][ax2pos])

            for fil_ind in range(len(fildat[bias][ax1pos][ax2pos])):
                dat = fildat[bias][ax1pos][ax2pos][fil_ind][lambind]
                assert dat[0] == yuklambda
                _, datfft, diagdatfft, daterr, diagdaterr, gfft, yukfft = dat

                chi_sqs = np.zeros(len(testalphas))
                diagchi_sqs = np.zeros(len(testalphas))

                for alphaind, testalpha in enumerate(testalphas):

                    chi_sq = 0
                    diagchi_sq = 0
                    N = 0

                    for resp in [0,1,2]:
                        if (ignoreX and resp == 0) or \
                           (ignoreY and resp == 1) or \
                           (ignoreZ and resp == 2):
                            continue
                        re_diff = datfft[resp].real - \
                                  (gfft[resp].real + testalpha * yukfft[resp].real )
                        im_diff = datfft[resp].imag - \
                                  (gfft[resp].imag + testalpha * yukfft[resp].imag )
                        if diag:
                            diag_re_diff = diagdatfft[resp].real - \
                                           (gfft[resp].real + testalpha * yukfft[resp].real )
                            diag_im_diff = diagdatfft[resp].imag - \
                                           (gfft[resp].imag + testalpha * yukfft[resp].imag )

                        #plt.plot(np.abs(re_diff))
                        #plt.plot(daterr[resp])
                        #plt.show()

                        chi_sq += ( np.sum( np.abs(re_diff)**2 / (0.5*(daterr[resp]**2)) ) + \
                                  np.sum( np.abs(im_diff)**2 / (0.5*(daterr[resp]**2)) ) )
                        if diag:
                            diagchi_sq += ( np.sum( np.abs(diag_re_diff)**2 / \
                                                    (0.5*(diagdaterr[resp]**2)) ) + \
                                            np.sum( np.abs(diag_im_diff)**2 / \
                                                    (0.5*(diagdaterr[resp]**2)) ) )

                        N += len(re_diff) + len(im_diff)

                    chi_sqs[alphaind] = chi_sq / (N - 1)
                    if diag:
                        diagchi_sqs[alphaind] = diagchi_sq / (N - 1)

                max_chi = np.max(chi_sqs)
                if diag:
                    max_diagchi = np.max(diagchi_sqs)

                max_alpha = np.max(testalphas)

                p0 = [max_chi/max_alpha**2, 0, 1]
                if diag:
                    diag_p0 = [max_diagchi/max_alpha**2, 0, 1]

                try:
                    popt, pcov = opti.curve_fit(parabola, testalphas, chi_sqs, \
                                                p0=p0, maxfev=100000)
                    if diag:
                        diagpopt, diagpcov = opti.curve_fit(parabola, testalphas, diagchi_sqs, \
                                                            p0=diag_p0, maxfev=1000000)
                except:
                    print("Couldn't fit")
                    popt = [0,0,0]
                    popt[2] = np.mean(chi_sqs)

                regular_con_val = con_val + np.min(chi_sqs)
                if diag:
                    diag_con_val = con_val + np.min(diagchi_sqs)

                # Select the positive root for the non-diagonalized data
                soln1 = ( -1.0 * popt[1] + np.sqrt( popt[1]**2 - \
                        4 * popt[0] * (popt[2] - regular_con_val)) ) / (2 * popt[0])
                soln2 = ( -1.0 * popt[1] - np.sqrt( popt[1]**2 - \
                        4 * popt[0] * (popt[2] - regular_con_val)) ) / (2 * popt[0])

                if diag:
                    diagsoln1 = ( -1.0 * diagpopt[1] + np.sqrt( diagpopt[1]**2 - \
                            4 * diagpopt[0] * (diagpopt[2] - diag_con_val)) ) / (2 * diagpopt[0])
                    diagsoln2 = ( -1.0 * diagpopt[1] - np.sqrt( diagpopt[1]**2 - \
                            4 * diagpopt[0] * (diagpopt[2] - diag_con_val)) ) / (2 * diagpopt[0])

                if soln1 > soln2:
                    alpha_con = soln1
                else:
                    alpha_con = soln2

                if diag:
                    if diagsoln1 > diagsoln2:
                        diagalpha_con = diagsoln1
                    else:
                        diagalpha_con = diagsoln2

                minalphas[fil_ind] = alpha_con
                if diag:
                    diag_minalphas[fil_ind] = diagalpha_con

            if plot:
                minfig, minaxarr = plt.subplots(1,2,figsize=(10,5),dpi=150)
                minaxarr[0].plot(minalphas)
                minaxarr[0].set_title('Min $\\alpha$ vs. Time', fontsize=18)
                minaxarr[0].set_xlabel('File Num', fontsize=16)
                minaxarr[0].set_ylabel('$\\alpha$ [arb]', fontsize=16)

                minaxarr[1].hist(minalphas, bins=20)
                minaxarr[1].set_xlabel('$\\alpha$ [arb]', fontsize=16)

                plt.tight_layout()
                plt.show()

    return minalphas

if not plot_just_current:
    gfuncs, yukfuncs, lambdas, lims = build_mod_grav_funcs(theory_data_dir)

    datafiles = bu.find_all_fnames(data_dir, ext=config.extensions['data'])

    datafiles = datafiles[file_inds[0]:file_inds[1]]

    if len(datafiles) == 0:
        print("Found no files in: ", data_dir)
        quit()

    fildat = get_data_at_harms(datafiles, gfuncs, yukfuncs, lambdas, lims, \
                               minsep=minsep, maxthrow=maxthrow, beadheight=beadheight, \
                               cantind=0, ax1='x', ax2='z', diag=diag, plottf=False, \
                               nharmonics=nharmonics, harms=harms, \
                               ext_cant_drive=True, ext_cant_ind=1, \
                               ignoreX=ignoreX, ignoreY=ignoreY, ignoreZ=ignoreZ)

    if compute_min_alpha:
        _ = get_alpha_vs_file(fildat, only_closest=only_closest, \
                              ignoreX=ignoreX, ignoreY=ignoreY, ignoreZ=ignoreZ, \
                              lamb_range=lamb_range, diag=diag, plot=True)

    newlambdas, alphas, diagalphas = \
                    get_alpha_lambda(fildat, only_closest=only_closest, \
                                     ignoreX=ignoreX, ignoreY=ignoreY, ignoreZ=ignoreZ, \
                                     lamb_range=lamb_range, diag=diag)

    outdat = [newlambdas, alphas, diagalphas]
    if save:
        np.save(savepath, outdat)

    if load:
        dat = np.load(savepath)
        newlambdas = dat[0]
        alphas = dat[1]
        diagalphas = dat[2]

fig, ax = plt.subplots(1,1,sharex='all',sharey='all',figsize=(5,5),dpi=150)
if diag:
    fig2, ax2 = plt.subplots(1,1,sharex='all',sharey='all',figsize=(5,5),dpi=150)

if not plot_just_current:
    ax.loglog(newlambdas, alphas, linewidth=2, label='95% CL')
    if diag:
        ax2.loglog(newlambdas, diagalphas, linewidth=2, label='95% CL')

ax.loglog(limitdata[:,0], limitdata[:,1], '--', label=limitlab, linewidth=3, color='r')
ax.loglog(limitdata2[:,0], limitdata2[:,1], '--', label=limitlab2, linewidth=3, color='k')
ax.grid()

ax.set_xlim(lambda_plot_lims[0], lambda_plot_lims[1])
ax.set_ylim(alpha_plot_lims[0], alpha_plot_lims[1])

ax.set_xlabel('$\lambda$ [m]')
ax.set_ylabel('$\\alpha$')

ax.legend(numpoints=1, fontsize=9)

ax.set_title(figtitle)

plt.tight_layout()

if diag:
    ax2.loglog(limitdata[:,0], limitdata[:,1], '--', label=limitlab, linewidth=3, color='r')
    ax2.loglog(limitdata2[:,0], limitdata2[:,1], '--', label=limitlab2, linewidth=3, color='k')
    ax2.grid()

    ax2.set_xlim(lambda_plot_lims[0], lambda_plot_lims[1])
    ax2.set_ylim(alpha_plot_lims[0], alpha_plot_lims[1])

    ax2.set_xlabel('$\lambda$ [m]')
    ax2.set_ylabel('$\\alpha$')

    ax2.legend(numpoints=1, fontsize=9)

    ax2.set_title(figtitle)

    plt.tight_layout()

plt.show()


from beautifultable import BeautifulTable
from Contact_new import Contact

class InMemoryImpl:

    contact_list = []

    @classmethod
    def addContact(cls):
        name = input("enter name: ")
        email = input("enter email: ")
        mobile = input("enter mobile: ")
        address = input("enter address: ")
        cls.contact_list.append(Contact(name, email, mobile, address))
        print(f"Contact is added succesfully!!! with name: {name} ")

    @classmethod
    def deleteContact(cls):
        name = input("enetr name to delete: ")
        contact = cls.get_contact_by_name(name)
        if contact:
            cls.contact_list.remove(contact)
            print(f"contact: {name} deleted successfully!!!!")
        else:
            print(f"contact with name : {name} not found")

    @classmethod
    def viewContact(cls):
        InMemoryImpl._paint(cls.contact_list)

    @classmethod
    def search(cls):
        if len(cls.contact_list) > 0 :
            name = input("enetr name to search: ")
            s_list = list(filter(lambda x:name.lower() in x.get_name().lower(),cls.contact_list))
            if len(s_list) > 0:
                InMemoryImpl._paint(s_list)
            else:
                print("there is no data found with searched name: {name}")
        else:
            print("Contact book is empty!!..... You cant search!!!")

    @classmethod
    def get_contact_by_name(cls, name):

        if len(cls.contact_list) > 0:
            contact = list(filter(lambda x:x.get_name().lower() == name.lower(), cls.contact_list))
        return contact[0] if contact else None

    @classmethod
    def updateContact(cls):
        name = input("enetr name to update: ")
        contact = cls.get_contact_by_name(name)
        if contact:
            print("1.Name 2.Email 3.Mobile 4.Address")
            ch = int(input("enter your choice: "))
            if ch == 1:
                print(f"Old name: {contact.get_name()}")
                name= input("entyer the new name: ")
                if name:
                    contact.set_name(name)

            elif ch == 2:
                print(f"Old email: {contact.get_email()}")
                email= input("entyer the new email: ")
                if email:
                    contact.set_email(email)

            elif ch == 3:
                print(f"Old mobile: {contact.get_mobile()}")
                mobile= input("entyer the new mobile: ")
                if mobile:
                    contact.set_mobile(mobile)

            elif ch == 4:
                print(f"Old address: {contact.get_address()}")
                address= input("entyer the new address: ")
                if address:
                    contact.set_address(address)
        else:
            print(f"contact not found with name: {name}")

    @staticmethod
    def _paint(lst):
        if len(lst) != 0:
            table=BeautifulTable()
            table.column_headers = ["Name", "Email", "Mobile", "Address"]
            for c in lst:
                table.append_row([c.get_name(),c.get_email(), c.get_mobile(), c.get_address()])
            print(table)
        else:
            print(f"Contact Book is empty!.....")


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

import logging
import xml.sax
import slpyser.xmlparser.handlers as handlers

from slpyser.model.abap_objects.AbapDictionary import AbapDictionary
from slpyser.model.abap_objects.AbapMessageClass import AbapMessageClass
from slpyser.model.abap_objects.AbapTextPool import AbapTextElement

class SAPLinkContentHandle(xml.sax.ContentHandler):
    """
    Implementation for SAX XML parser handle SAPLink file syntax.
    """

    def __init__(self):
        """
        Constructor
        """
        self.__logger = logging.getLogger(__name__)
        xml.sax.ContentHandler.__init__(self)
        self._matrix_element_case_handler = {
            # TextPool elements
            'TEXTPOOL': [
                self._startTextPool,
                self._charactersTextPool,
                self._endTextPool
            ],
            'TEXTELEMENT': [
                self._startTextPoolTextElement,
                self._charactersTextPoolTextElement,
                self._endTextPoolTextElement
            ],

            # Message Class elements
            'MSAG': [
                self._startMessageClass,
                None,
                self._endMessageClass
            ],
            'T100': [
                self._startMessageClassMessage,
                None,
                None,
            ],

            # General elements
            'SOURCE': [
                self._startSourceCode,
                self._charactersSourceCode,
                self._endSourceCode
            ],
            'LANGUAGE': [
                self._startTextLanguage,
                self._charactersTextLanguage,
                self._endTextLanguage
            ],
        }
        """
        Each element have three handlers, declared in that order:
          1st: handle start of an element (retrieve element attributes);
          2nd: handle contents of an element (retrieve data inside element);
          3rd: handle end of an element.
        """
        self.__unhandled_element = [
            self._startUnhandled,
            self._charactersUnhandled,
            self._endUnhandled
        ]

        # Attributes to be returned after parsing
        self._abap_message_classes = {}

        # Internal attributes, store references of current processed abap objects
        self.__current_source_code_reference = None
        self.__current_text_pool_reference = None
        self.__current_class_documentation_reference = None
        self.__current_text_language = None
        self.__current_message_class = None

        # Helper attributes
        self.__current_tag = None
        self.__current_tag_stack = []

        # Decoupled parsers
        self.__programs_parser = handlers.Program(owner=self)
        self._matrix_element_case_handler.update(self.__programs_parser.map_parse())
        self.__ddic_parser = handlers.DDIC(owner=self)
        self._matrix_element_case_handler.update(self.__ddic_parser.map_parse())
        self.__class_library_parser = handlers.ClassLibrary(owner=self)
        self._matrix_element_case_handler.update(self.__class_library_parser.map_parse())
        self.__function_group_parser = handlers.FunctionGroup(owner=self)
        self._matrix_element_case_handler.update(self.__function_group_parser.map_parse())

    @property
    def abapClasses(self):
        return self.__class_library_parser.parsed_classes

    @property
    def abapFunctionGroups(self):
        return self.__function_group_parser.parsed_function_groups

    @property
    def abapMessageClasses(self):
        return self._abap_message_classes

    @property
    def abapDictionary(self):
        return AbapDictionary.from_ddic_handler(self.__ddic_parser)

    @property
    def abapPrograms(self):
        return self.__programs_parser.parsed_programs

    def startElement(self, name, attrs):
        """Parses start element"""
        # Upper case on name because SAPLINK haven't used same case on all elements.
        self.__current_tag = name.upper()
        self.__current_tag_stack.append(self.__current_tag)
        start_element_handler = self._matrix_element_case_handler.get(self.__current_tag, self.__unhandled_element)[0]
        if start_element_handler is not None:
            start_element_handler(name.upper(), attrs)

    def characters(self, content):
        """
        Parses inner contents of current element.
        This method is called for each new line inside that element.
        """
        characters_handler = self._matrix_element_case_handler.get(self.__current_tag, self.__unhandled_element)[1]
        if characters_handler is not None:
            characters_handler(content)

    def endElement(self, name):
        """Parses end of element."""
        if self.__current_tag != name.upper():
            self.__logger.error('ERROR parsing file, current element was %s but closing element was %s' , self.__current_tag, name.upper())
        end_element_handler = self._matrix_element_case_handler.get(self.__current_tag, self.__unhandled_element)[2]
        if end_element_handler is not None:
            end_element_handler(name.upper())
        self.__current_tag_stack.pop()
        # FIXME: Append None to currentTagStack to avoid little hack?
        self.__current_tag = self.__current_tag_stack[-1] if len(self.__current_tag_stack) > 0 else None

    # Below are declared method to properly handle elements and its contents

    def _startMessageClass(self, name, attrs):
        self.__logger.debug('Start message class')
        name = attrs.get('ARBGB')
        original_language = attrs.get('MASTERLANG')
        responsible = attrs.get('RESPUSER', '')
        short_text = attrs.get('STEXT', '')

        message_class = AbapMessageClass(Name=name,
                                         OriginalLanguage=original_language,
                                         Responsible=responsible,
                                         ShortText=short_text)
        self.__current_message_class = message_class

    def _endMessageClass(self, name):
        msg_class = self.__current_message_class
        self._abap_message_classes[msg_class.name] = msg_class
        self.__current_message_class = None

    def _startMessageClassMessage(self, name, attrs):
        self.__logger.debug('Start Message Class Message')
        language = attrs.get('SPRSL')
        number = attrs.get('MSGNR')
        text = attrs.get('TEXT')

        message = AbapMessageClass.Message(Language=language,
                                           Number=number,
                                           Text=text)

        if self.__current_message_class.language_mapping.get(language) == None:
            self.__current_message_class.language_mapping[language] = {}

        self.__current_message_class.language_mapping[language][number] = message

    def _startSourceCode(self, name, attrs):
        self.__logger.debug('Start Source Code')

    def _charactersSourceCode(self, content):
        self.__current_source_code_reference.source_code.append(content)

    def charactersSourceCode(self, content):
        self._charactersSourceCode(content)

    def _endSourceCode(self, name):
        self.__logger.debug('End Source Code')

    def _startTextLanguage(self, name, attrs):
        self.__logger.debug('Start Text Language')
        self.__current_text_language = attrs.get('SPRAS')
        # Initializing language dict
        if self.__current_text_pool_reference is not None:
            self.__current_text_pool_reference.language_mapping[self.__current_text_language] = {}
        elif self.__current_class_documentation_reference is not None:
            self.__current_class_documentation_reference.languageMappint[self.__current_text_language] = []

    def _charactersTextLanguage(self, content):
        pass

    def _endTextLanguage(self, name):
        self.__logger.debug('End Text Language')
        self.__current_text_language = None

    def _startTextPool(self, name, attrs):
        self.__logger.debug('Start Text Pool')

    def _charactersTextPool(self, content):
        pass

    def _endTextPool(self, name):
        self.__logger.debug('End Text Pool')

    def _startTextPoolTextElement(self, name, attrs):
        self.__logger.debug('Start Text Pool Text Element')
        text_id = attrs.get('ID')
        key = attrs.get('KEY')
        entry = attrs.get('ENTRY')
        length = attrs.get('LENGTH')
        text_element = AbapTextElement(TextId=text_id,
                                       TextKey=key,
                                       TextEntry=entry,
                                       Length=length)
        if self.__current_text_pool_reference is not None:
            self.__current_text_pool_reference.addTextElement(Language=self.__current_text_language,
                                                              TextElement=text_element)
        else:
            self.__logger.warning('[FIXME] A text pool''s entry "%s" was found but the current abap object wasn''t expecting a text pool.', entry)

    def _charactersTextPoolTextElement(self, content):
        pass

    def _endTextPoolTextElement(self, name):
        self.__logger.debug('End Text Pool Text Element')

    def _startUnhandled(self, name, attrs):
        self.__logger.warning('Start of an unhandled element: %s', name)

    def _charactersUnhandled(self, content):
        self.__logger.warning('Content of unhandled tag: %s', content)

    def _endUnhandled(self, name):
        self.__logger.warning('End of an unhandled element: %s', name)

    def set_current_source_code_reference(self, source_reference):
        self.__current_source_code_reference = source_reference
        source_reference.source_code = []

    def finalize_source_code(self):
        """
        Join the source code's array into a string, and clean it's reference from parser.
        """
        self.__current_source_code_reference.source_code = ''.join(self.__current_source_code_reference.source_code)
        self.__current_source_code_reference = None

    def set_current_textpool_reference(self, textpool_reference):
        self.__current_text_pool_reference = textpool_reference

    def finalize_textpool(self):
        self.__current_text_pool_reference = None