"""
The :py:mod:`optimization` module contains functions to load the optimizer,
create the starting samples and run the optimization.
"""

import os
import imp
from shutil import copyfile
from pyDOE import lhs
from rheia.CASES.determine_stoch_des_space import load_case, check_dictionary
import numpy as np
import pandas as pd
#######################
# optimizer functions #
#######################

def parse_available_opt():
    """

    Parse all available optimizers. In this version,
    only NSGA-II is available.

    Returns
    -------
    methods : list of tuples
        The available optimizers with the corresponding classes.

    """

    opt_dir = os.path.join(os.path.split(
        os.path.dirname(
            os.path.abspath(__file__)))[0],
        'OPT')

    # get the optimizer modules
    files = [f for f in os.listdir(opt_dir) if f.endswith('algorithms.py')]
    methods = []
    for file in files:
        obj = imp.load_source(file.split('.')[0], os.path.join(opt_dir, file))
        tmp = obj.return_opt_methods()
        for method in tmp:
            methods.append((method, obj))

    return methods

def load_optimizer(optimizer):
    """

    Load the selected optimizer.

    Parameters
    ----------
    optimizer : string
        The name of the optimizer (currently 'NSGA2').

    Returns
    -------
    opt_obj : object
        The optimization object.

    """

    opt_list = parse_available_opt()
    optimizers = [elem[0] for elem in opt_list]

    # check if optimizer exists and load optimization module
    if optimizer not in optimizers:
        raise KeyError('Optimizer is not available!')

    # get object from optimizer class
    for opt in opt_list:
        if optimizer == opt[0]:
            opt_obj = opt[1].return_opt_obj(optimizer)

    return opt_obj

####################
# starting samples #
####################

def check_existing_results(run_dict, space_obj):
    """
    Check if previously generated results exists in the provided results
    directory.

    Parameters
    ----------
    run_dict : dict
        The dictionary with user-defined values for
        the characterization of the optimization.
    space_obj : object
        The object with information on the design space and stochastic space

    Returns
    -------
    start_from_last_gen : bool
        Boolean that indicates if results exist in the considered result
        directory.

    """

    # path of the population file
    pop_file = os.path.join(os.path.split(os.path.dirname(
        os.path.abspath(__file__)))[0],
        'RESULTS',
        space_obj.case,
        list(run_dict['objectives'].keys())[0], run_dict['results dir'],
        'population.csv')

    # path of the fitness file
    fitness_file = os.path.join(os.path.split(os.path.dirname(
        os.path.abspath(__file__)))[0],
        'RESULTS',
        space_obj.case,
        list(run_dict['objectives'].keys())[0], run_dict['results dir'],
        'fitness.csv')

    # check if the population and fitness file exist
    start_from_last_gen = False
    if os.path.isfile(fitness_file) and os.path.isfile(pop_file):

        start_from_last_gen = True

    return start_from_last_gen

def scale_samples_to_design_space(nondim_doe, space_obj):
    """
    Scales the starting sample to the given design space.

    Parameters
    ----------
    nondim_doe : ndarray
        The non-dimensionalized design of experiment.
    space_obj : object
        The object with information on the design space and stochastic space

    Returns
    -------
    dim_doe : ndarray
        The design of experiment scaled up to the design space.

    """

    dim_doe = np.zeros(nondim_doe.shape)
    for j in range(space_obj.n_dim):
        dim_doe[:, j] = ((space_obj.u_b[j] - space_obj.l_b[j]) *
                         nondim_doe[:, j] + space_obj.l_b[j])

    return dim_doe

def write_starting_samples(doe, filename):
    """

    Writes the starting samples to file.

    Parameters
    ----------
    doe : list
        The set of starting samples.
    filename : string
        The path to the filename for the starting samples.

    """
    with open(filename, 'w') as file:
        for x_in in doe:
            if not isinstance(x_in, list):
                x_in = x_in.tolist()
            for item in x_in:
                file.write('%.8f ' % item)
            file.write('\n')

def create_starting_samples(run_dict, space_obj, start_from_last_gen):
    """

    Load the starting samples for the optimization run.

    Parameters
    ----------
    run_dict : dict
        The dictionary with user-defined values for
        the characterization of the optimization.
    space_obj : object
        The object with information on the design space and stochastic space
    start_from_last_gen : bool
        Boolean that determines if the starting samples
        start from a previously generated population.

    """

    # define folder to put starting samples file
    doe_path = os.path.join(os.path.split(
        os.path.dirname(
            os.path.abspath(__file__)))[0],
        'OPT',
        'INPUTS',
        space_obj.case,
        '%iD' %
        space_obj.n_dim)

    # check if folder exists in INPUTS
    # if not, create one
    if not os.path.exists(doe_path):
        os.makedirs(doe_path)

    # create the doe set of samples
    doe_filename = os.path.join(doe_path,
                                'DOE_n%i.csv' % run_dict['population size'])

    if not start_from_last_gen:
        # if the starting population needs to be created
        if 'AUTO' in run_dict['x0'][0]:

            # generate the starting population randomly
            if 'RANDOM' in run_dict['x0'][1]:
                ddoe = np.random.random(
                    (run_dict['population size'], space_obj.n_dim))

            # generate the starting population
            # based on Latin Hypercube Sampling
            if 'LHS' in run_dict['x0'][1]:
                ddoe = lhs(space_obj.n_dim,
                           samples=run_dict['population size'])

            # scale the starting samples
            doe = scale_samples_to_design_space(ddoe, space_obj)

            # Write starting samples to file
            write_starting_samples(doe, doe_filename)

        else:
            # the starting population is provided in a custom file
            doe_custom = os.path.join(os.path.split(
                os.path.dirname(
                    os.path.abspath(__file__)))[0],
                'CASES',
                space_obj.case,
                run_dict['x0'][1])

            # check if the custom file exists
            if not os.path.isfile(doe_custom):
                raise NameError(
                    """The initial population file %s
                    is not found in the case folder.""" %
                    os.path.basename(doe_custom))

            copyfile(doe_custom, doe_filename)

    else:
        # the starting population is the final generation from the existing
        # population in the result directory
        doe_custom = os.path.join(os.path.split(
            os.path.dirname(
                os.path.abspath(__file__)))[0],
            'RESULTS',
            space_obj.case,
            list(run_dict['objectives'].keys())[0],
            run_dict['results dir'],
            'population.csv')

        df = pd.read_csv(doe_custom, header=None)
        df.drop(df.tail(1).index,inplace=True)

        rows = df.tail(run_dict['population size']).to_numpy()

        doe = []
        for line in rows:
            dummy = []
            for l in line:
                dummy.append(float(l))
            doe.append(dummy)

        # check if the size of the existing population matches with the
        # provided one in the optimization dictionary
        if len(doe) == run_dict['population size']:
            write_starting_samples(doe, doe_filename)
        else:
            raise ValueError(""" The defined population size does not match
                                 the population size from a previous run in
                                 this result directory.""")

########################
# run the optimization #
########################

def run_opt(run_dict, design_space='design_space.csv'):
    """
    This function runs the optimization pipeline.
    First, the case, optimizer and configuration
    are loaded. Thereafter, the starting samples
    are created, the specific optimization class
    instantiated and the :py:meth:`run_optimizer`
    method is called.

    Parameters
    ----------
    run_dict : dict
        The dictionary with user-defined values for
        the characterization of the optimization.
    design_space : string, optional
        The design_space filename. The default is 'design_space.csv'.

    """

    # evaluate if the optimization dictionary is properly characterized
    check_dictionary(run_dict)

    # load the object on the design space, the evaluation function
    # and the params provided for each model evaluation
    space_obj, eval_func, params = load_case(run_dict, design_space)

    # add the evaluation function to the optimization dictionary
    run_dict['evaluate'] = eval_func

    # load optimizer class
    opt_class = load_optimizer('NSGA2')

    # check if previous results in this result directory exist
    start_from_last_gen = check_existing_results(run_dict, space_obj)

    # define starting samples
    create_starting_samples(run_dict, space_obj, start_from_last_gen)

    # optimizer object
    res = opt_class(run_dict, space_obj, start_from_last_gen, params)

    # run the optimizer
    res.run_optimizer()


#!/usr/bin/env python3
import pathlib

def partOne():
    """ Given seven segment signals, return how many times 1, 4, 7, 8 show up."""
    filePath = pathlib.Path(__file__).parent.resolve()
    finalCounts = [0] * 10

    with open(f'{filePath}/input.txt') as f:
        lines = f.readlines()
        for line in lines:
            parts = line.split('|')
            outputList = parts[1].split()
            for segment in outputList:
                length = len(segment)
                if length == 2:
                    finalCounts[1] += 1
                elif length == 4:
                    finalCounts[4] += 1
                elif length == 3:
                    finalCounts[7] += 1
                elif length == 7:
                    finalCounts[8] += 1

        result = sum(finalCounts)

    return result

def partTwo():
    """ Given seven segment signals, return how many times 1, 4, 7, 8 show up."""
    filePath = pathlib.Path(__file__).parent.resolve()
    result = 0
    numSegments = [0] * 10

    with open(f'{filePath}/input.txt') as f:
        lines = f.readlines()
        for line in lines:
            numSegments = [0] * 10
            parts = line.split('|')

            # figure out number segments
            guideList = parts[0].split()
            guideList.sort(key=len)

            for index, seg in enumerate(guideList):
                guideList[index] = "".join(sorted(seg))

            # save 7 and 8
            numSegments[7] = guideList[1]
            numSegments[8] = guideList[9]

            # figure out 1 and 4
            numSegments[1] = numberOne = guideList[0]
            numSegments[4] = numberFour = guideList[2]

            # figure out 2 missing letters (diff)
            numberOneSet = set(numberOne)
            numberFourSet = set(numberFour)
            difference = numberFourSet.symmetric_difference(numberOneSet)
            difference = "".join(list(sorted(difference)))

            numberFive = None
            # find len(5) with diff letters - this is number 5
            for index in range(3,6):
                if difference[0] in guideList[index] and difference[1] in guideList[index]:
                    numSegments[5] = numberFive = guideList[index]

            # find len(5) with letters from numberOne - this is number 3; other is number 2
            numberThree = None
            for index in range(3,6):
                if guideList[index] == numberFive:
                    continue
                elif numberOne[0] in guideList[index] and numberOne[1] in guideList[index]:
                    numSegments[3] = numberThree = guideList[index]
                else:
                    numSegments[2] = numberTwo = guideList[index]

            # find len(6) with one of diff letters missing - this is number 0
            for index in range(6,9):
                if difference[0] not in guideList[index] or difference[1] not in guideList[index]:
                    numSegments[0] = numberZero = guideList[index]

            # find len(6) with both letters from numberOne - this is number 9; other number is 6
            for index in range(6,9):
                if guideList[index] == numberZero:
                    continue
                elif numberOne[0] in guideList[index] and numberOne[1] in guideList[index]:
                    numSegments[9] = numberNine = guideList[index]
                else:
                    numSegments[6] = numberSix = guideList[index]

            outputList = parts[1].split()
            currentNumber = ""
            for segment in outputList:
                segment = "".join(sorted(segment))
                currentNumber += str(numSegments.index(segment))

            result += int(currentNumber)

    return result

if __name__ == "__main__":
    print(f"partOne: {partOne()}")
    print(f"partTwo: {partTwo()}")


from joblib import load, dump
import pandas as pd
from flask import jsonify, Blueprint

from sklearn.svm import SVC
from sklearn.metrics import classification_report, accuracy_score, confusion_matrix
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.pipeline import Pipeline

import os

CLASSIFIER = None
PICKLE_CLASSIFIER = "./sklassifier.pkl"

def train_model():
    """Tains the model, must be run at the beginning of the execution to have the classifier loaded.

    Returns:
        dict: A dictionary with the classifier reports.
    """
    global CLASSIFIER
    if os.path.exists(PICKLE_CLASSIFIER):
        CLASSIFIER = load(PICKLE_CLASSIFIER)
        return

    df = pd.read_csv("./model/data/phising-set.csv")
    df.isna().sum()
    df = df.dropna()

    email_type_counts = df["Email Type"].value_counts()
    print(email_type_counts)

    Safe_Email = df[df["Email Type"] == "Safe Email"]
    Phishing_Email = df[df["Email Type"] == "Phishing Email"]
    Safe_Email = Safe_Email.sample(Phishing_Email.shape[0])

    Data = pd.concat([Safe_Email, Phishing_Email], ignore_index=True)

    X = Data["Email Text"].values
    y = Data["Email Type"].values
    X_train, x_test, y_train, y_test = train_test_split(
        X, y, test_size=0.3, random_state=0
    )

    CLASSIFIER = Pipeline(
        [
            ("tfidf", TfidfVectorizer()),
            ("classifier", RandomForestClassifier(n_estimators=10)),
        ]
    )

    CLASSIFIER.fit(X_train, y_train)
    with open(PICKLE_CLASSIFIER, "wb") as pickle_file:
        dump(CLASSIFIER, pickle_file)

    y_pred = CLASSIFIER.predict(x_test)

    return {
        "accuracy": accuracy_score(y_test, y_pred),
        "confusion": confusion_matrix(y_test, y_pred),
        "report": classification_report(y_test, y_pred),
    }

def predict_email(_sender, _subject, _body):
    """Uses the Classifier model to predict if the email is a phishing email or not.

    Args:
        _sender (str): The email sender
        _subject (str): The email subject
        _body (str): The email body

    Returns:
        Response: A jsonify response for flask with a probabilities array and the prediction.
    """
    global CLASSIFIER
    pack = f"{_sender}\n{_subject}\n{_body}"
    if not CLASSIFIER:
        return None

    probs = CLASSIFIER.predict_proba([pack])
    pred = CLASSIFIER.predict([pack])
    # print(probs, pred)
    # print(type(probs))
    # print(pred[0][0], pred[0][1])
    # print(type(pred))
    pred = pred.tolist()
    probs = probs.tolist()
    return {"prediction": pred[0], "probabilities": {
        "safe": probs[0][0],
        "phishing": probs[0][1]
    }}

if __name__ == "__main__":
    train_model()
    res = predict_email(
        "Tiny Content",
        "noreply@naisit.com",
        """Daer Bruno Ramirez Bonilla,

Welcome to the world of programming logic, algorithms, and problem-solving.

Your professor has submitted your email address so you can receive a copy of "The Basics of a Complicated Concepts (Programming Logic)" e-book, published and copyrighted by Naisit (Tiny Content) publishing. This e-book will be updated regularly. You will be notified when a new version is available for you to download. Your copy is watermarked with your name and email address to prevent any illegal distributions.

Please follow the URL to download your e-book.

URL: https://tinycontent.naisit.com/api/download/6327e789937000676d09c666""",
    )

    print(res)


# Pablo de Andres
# Deep Learning lab, ML track, exercise 4
# Uni Freiburg WS 2017/18

import argparse
import numpy as np
import os
import sys
import tempfile

from main import Data
from unet import unet

import tensorflow as tf

FLAGS = None

# For running on CPU
# os.environ['CUDA_VISIBLE_DEVICES'] = '-1'
# tensorboard --logdir=/home/andresp/lab/tensorflow/

def main(_):

  data = Data()

  # Create the model
  x = tf.placeholder(tf.float32, [None, 300, 300, 1])

  # Define loss and optimizer
  y_ = tf.placeholder(tf.int32, [None, 116, 116])

  # Build the graph for the deep net
  y_conv = unet(x)

  with tf.name_scope('loss'):
    loss = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=y_, logits=y_conv)
  loss = tf.reduce_mean(loss)
  tf.summary.scalar('loss', loss)

  with tf.name_scope('AdamOptimizer'):
    train_step = tf.train.AdamOptimizer(0.0001, 0.95, 0.99).minimize(loss)

  with tf.name_scope('Accuracy'):
    # Training accuracy
    prediction = tf.argmax(y_conv, 3) # argmax the 3rd dimension, the label
    correct_pix_pred = np.sum(prediction == y_)
    incorrect_pix_pred = np.sum(prediction != y_)
    n_pix = 116 * 116
    train_acc = correct_pix_pred / (incorrect_pix_pred + n_pix)
    # Validation accuracy
    val_acc = 0
    val_images = data.get_test_image_list_and_label_list()
    for i in range(len(val_images[0])):
      x_val = val_images[0][i]
      y_val = val_images[1][i]
      y_conv_acc = unet(x_val)
      prediction = tf.argmax(y_conv_acc, 3)
      correct_pix_pred = np.sum(prediction == y_val)
      incorrect_pix_pred = np.sum(prediction != y_val)
      n_pix = 116 * 116
      val_acc += correct_pix_pred / (incorrect_pix_pred + n_pix)

  train_acc = tf.summary.scalar('Training accuracy', train_acc)
  val_acc = tf.summary.scalar('Validation accuracy', val_acc)

  graph_location = tempfile.mkdtemp()
  print('Saving graph to: %s' % graph_location)
  writer = tf.summary.FileWriter(graph_location)
  writer.add_graph(tf.get_default_graph())

  with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    writer = tf.summary.FileWriter(FLAGS.log_dir + '/assignment04', sess.graph)
    for i in range(400):
      batch = data.get_train_image_list_and_label_list()
      if i % 100 == 0:
        train_acc, val_acc = sess.run([train_acc, val_acc],
                                      feed_dict={x: batch[0], y_: batch[1]})
        writer.add_summary(train_acc, i)
        writer.add_summary(val_acc, i)
        print('step %d'% (i))
      train_step.run(feed_dict={x: batch[0], y_: batch[1]})
    writer.close()

if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument('--data_dir', type=str,
                      default='/tmp/tensorflow/mnist/input_data',
                      help='Directory for storing input data')
  parser.add_argument('--log_dir', type=str,
                      default=os.path.join(os.getenv('HOME', '/home'),
                                           'lab/tensorflow'),
                      help='Summaries log directory')
  FLAGS, unparsed = parser.parse_known_args()
  tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)


import pygame
import random
import queue
import pathfinding

# Initializing graphics
pygame.init()
win = pygame.display.set_mode((1280, 720))
surface_size = (256, 144)
display = pygame.Surface((surface_size))
clock = pygame.time.Clock()

# Variables
running = True  # Just a smol var i use to close the game
mouse_left_button_down = False
mouse_right_button_down = False
tile_size = 8  # I RECOMMEND NOT CHANGING THIS VALUE AS IM NOT SURE WHAT MIGHT END UP HAPPENNING BY DOING SO
fps = 60
surf_x = 0
surf_y = 0
xscroll = 0
yscroll = 0
scrollsp = 1  # Set this to negative to inverse scrolling controls

# Tilemap
tilemap = [
    [' ', ' ', ' '],
    [' ', ' ', ' '],
    [' ', ' ', ' ']
]
current_tile = 'H'
tilemap_key_file = {
    'H': pygame.image.load('sprites/wall.png')
}

def draw_map_from_array(two_dimensional_array, key_file_dict: dict, display_to_draw_to, xpos=0, ypos=0, tile_size=tile_size):
    '''
    two_dimensional_array: This is the 2D array which holds your entire map
    key_file_dict: dictionary that mentions which value in the 2D Array map corrosponds to which image to draw.
    '''
    ty = 0
    for row in two_dimensional_array:
        tx = 0
        for tile in row:
            if tile in key_file_dict:
                display_to_draw_to.blit(key_file_dict[tile], ((tx*tile_size)+xpos, (ty*tile_size)+ypos-(
                    (tilemap_key_file[current_tile].get_rect().size[1])-tile_size)))
            tx += 1
        ty += 1

def add_tile_to_tilemap(two_dimensional_array: list, value_to_insert, xpos_in_array, ypos_in_array):

    # Extending the Array to the point at which it can atleast hold the tile
    while len(two_dimensional_array) <= ypos_in_array:
        two_dimensional_array.append(list())
    while len(two_dimensional_array[ypos_in_array]) <= xpos_in_array:
        two_dimensional_array[ypos_in_array].append(' ')

    two_dimensional_array[ypos_in_array][xpos_in_array] = value_to_insert

def get_2d_array_len(array):
    xlen = 0
    for row in array:
        if len(row) > xlen:
            xlen = len(row)
    ylen = len(array)

    return (xlen, ylen)

# Main Graphics Loop
while running:
    clock.tick(fps)

    # Calculating the position of the tiles
    mx, my = pygame.mouse.get_pos()
    tx, ty = int(round(((mx)/5)-surf_x)), int(round(((my)/5)-surf_y))

    while tx % tile_size != 0:
        tx -= 1
    while ty % tile_size != 0:
        ty -= 1

    # Clearing the screen
    win.fill((0, 0, 0))
    display.fill((0, 0, 50))

    # Input
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            f = open('save.py', 'w')
            f.write(str(tilemap))
            f.close()
            running = False
        if event.type == pygame.MOUSEBUTTONDOWN:
            if event.button == 1:
                mouse_left_button_down = True
            elif event.button == 3:
                mouse_right_button_down = True
        elif event.type == pygame.MOUSEBUTTONUP:
            if event.button == 1:
                mouse_left_button_down = False
            elif event.button == 3:
                mouse_right_button_down = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                yscroll = scrollsp
            elif event.key == pygame.K_DOWN:
                yscroll = -scrollsp
            elif event.key == pygame.K_LEFT:
                xscroll = scrollsp
            elif event.key == pygame.K_RIGHT:
                xscroll = -scrollsp
        elif event.type == pygame.KEYUP:
            if event.key == pygame.K_UP:
                yscroll = 0
            elif event.key == pygame.K_DOWN:
                yscroll = 0
            elif event.key == pygame.K_LEFT:
                xscroll = 0
            elif event.key == pygame.K_RIGHT:
                xscroll = 0

    # Scroll
    surf_x += xscroll
    surf_y += yscroll

    # Acting on input
    if not tx < 0 and not ty < 0:
        if mouse_left_button_down:
            add_tile_to_tilemap(tilemap, 'H', int(
                round(tx/tile_size)), int(round(ty/tile_size)))
        if mouse_right_button_down:
            add_tile_to_tilemap(tilemap, ' ', int(
                round(tx/tile_size)), int(round(ty/tile_size)))

        # Drawing tile at the current position
        display.blit(tilemap_key_file[current_tile], (tx+surf_x, ty-(
            (tilemap_key_file[current_tile].get_rect().size[1])-tile_size)+surf_y))

    # Drawing the boundaries
    for line in [
        {'start': [0, 0], 'end':[(get_2d_array_len(tilemap)[0])*tile_size, 0]},
        {'start': [(get_2d_array_len(tilemap)[0])*tile_size, 0],
         'end':[(get_2d_array_len(tilemap)[0])*tile_size, (len(tilemap))*tile_size]},
        {'start': [(get_2d_array_len(tilemap)[0])*tile_size, (len(tilemap))
                   * tile_size], 'end':[0, (len(tilemap))*tile_size]},
        {'start': [0, (len(tilemap))*tile_size], 'end':[0, 0]}
    ]:
        line['start'][0] += surf_x
        line['start'][1] += surf_y
        line['end'][0] += surf_x
        line['end'][1] += surf_y

        pygame.draw.line(display, (200, 200, 200), line['start'], line['end'])

    # Updating the display
    draw_map_from_array(tilemap, tilemap_key_file,
                        display, xpos=surf_x, ypos=surf_y)
    win.blit(pygame.transform.scale(display, (1280, 720)), (0, 0))
    pygame.display.update()


from texttable import Texttable

t = Texttable()
t.add_row(['Process','Memory acquired','Allocated?','internalfragmentation'])

process_memory = []
tif=0
total_memory = int(input("Enter the total memory available : "))
blocksize = int(input("Enter the blocksize: "))
numOfBlocks = int(total_memory/blocksize)
processes_num = int(input("Enter number of processes:"))
externalfrag=total_memory - (processes_num*blocksize)
if(processes_num <= numOfBlocks):
    for i in range(0,processes_num):
        print("Enter the size of process",i+1,'in bytes : ')
        mem = int(input())
        process_memory.append(mem)
    print("Number of block in memory are:",numOfBlocks)
    for i in range(0,processes_num):
        internalfrag = blocksize - process_memory[i]
        if internalfrag >= 0:
            tif += internalfrag
        else:
            internalfrag = blocksize
        if(process_memory[i] > blocksize):
            isAllocated = 'NO'
        else:
            isAllocated = 'YES'
        t.add_row([i+1,process_memory[i],isAllocated,internalfrag])

    print(t.draw())
    print("External fragmentation : ",externalfrag)
    print("Total internal fragmentation : ",tif)
else:
    print("Number of processes is more  than number of partitions")


from Utility_Tools.mapping_functions import linear_to_logistic as lin2sigmoid
from Utility_Tools.mapping_functions import linear_to_linear as lin2lin
from nltk.tokenize import word_tokenize

def get_octave_placement_sigmoid(text: str):
    """
    Function to map the length of a given text to an octave via a sigmoid function.
    :param text: str
    :return: int
    """
    length = len(text)
    return int(lin2sigmoid(length, 0, 280, 96, 24, -0.3)) // 12

def get_octave_placement_linear(text: str):
    """
    Function to map the length of a given text to an octave via a linear mapping function.
    :param text: str
    :return: int
    """
    length = len(text)
    if length > 144:
        length = 144
    elif length < 0:
        length = 0
    else:
        length = length
    return int(lin2lin(length, 0, 144, 96, 24)) // 12

def get_octave_placement_piecewise(text: str):
    """
    Function to map the length of a given text to an octave via special piece-wise logic.
    :param text: str
    :return: int
    """
    char_len = len(text)
    if char_len <= 29:
        # Short texts
        return int(lin2lin(char_len, 0, 29, 96, 60)) // 12
    else:
        tokens = word_tokenize(text)
        tokens_len = len(tokens)
        # average word length in english is 4.7 characters
        # round up to 5
        # max characters in text message is 160
        # average num words in max text message len ~ 27 (160 characters = 5 characters * num_words + num_spaces)
        if tokens_len > 27:
            tokens_len = 27
        return int(lin2lin(tokens_len, 0, 27, 60, 24)) // 12

if __name__ == "__main__":
    texts = [
        "and",
        "and above and",
        "to infinite and beyond",
        "here is a string with eight words or so",
        "Here is a long string, LORUM IPSUM, LORUM IPSUM, LORUM IPSUM, LORUM IPSUM, LORUM IPSUM, LORUM IPSUM, LORUM IPSUM"
    ]
    for text in texts:
        print(get_octave_placement_piecewise(text))


import numpy as np
from pathlib import Path

PRED_TXT='preds.txt'
SCENE_TXT='/mnt/HD_2/luojiapeng/scene_recognition/data/valset/scenes/labels.txt'

if __name__ == '__main__':
    preds = np.loadtxt(PRED_TXT,dtype=str).tolist()
    correct = 0
    total = 0
    gt = np.loadtxt(SCENE_TXT, dtype=str).tolist()
    gt = dict(gt)

    for p in preds:
        img_name = Path(p.split(':')[0]).name
        pred_scene = p.split(':')[1].split(',')[1]
        if pred_scene == gt[img_name]:
            correct += 1
        total += 1
    print('scene accuracy: %.4f' % (correct / total))


from django.shortcuts import render, get_object_or_404
from django.http import HttpResponse
from .models import Topic, Entry, Link
from django.http import HttpResponseRedirect
from django.urls import reverse
from .forms import TopicForm, EntryForm, DeleteEntryForm, DeleteTopicForm
from django.contrib.auth.decorators import login_required
# Create your views here.

def index(request):
    t = Topic.objects.order_by("title")
    context = {'topics':t}
    return render(request, "index.html", context)
    #return HttpResponse("
Hello Django
")

@login_required
def topics(request):
    t = Topic.objects.filter(owner=request.user).order_by("title")
    context = {"topics": t}
    return render(request, "topics.html", context)

def resources(request):
    topics = Topic.objects.all()
    topics_links = {}
    for t in topics:
        links = t.link_set.all()
        topics_links[t] = links
    context = {"topics":topics_links} # topics_links ={topic1: links, topic2: links....}

    return render(request, "resources.html", context)

@login_required
def topic(request, topic_id):
    '''show a single topic and all its entries'''
    topic = Topic.objects.filter(owner=request.user).get(id=topic_id)
    entries = topic.entry_set.order_by('date_added')
    context = {"topic": topic, "entries": entries}
    return render(request,"topic.html", context)

@login_required
def new_topic(request):
    '''Add a new topic'''

    if request.method != 'POST':
        form = TopicForm()
    else:
        form = TopicForm(request.POST, request.user)
        if form.is_valid():
            new_topic = form.save(commit=False)
            new_topic.owner = request.user
            new_topic.save()
            return HttpResponseRedirect(reverse('logs:topics'))
    context = {'form': form}
    return render(request, 'new_topic.html', context)

@login_required
def edit_topic(request, topic_id):
    '''Edit a new topic'''
    topic = Topic.objects.get(id = topic_id)
    num = len(topic.entry_set.all()) # number of entries under this topic
    if request.method != 'POST':
        form = TopicForm(instance = topic)
    else:
        form = TopicForm(instance=topic, data=request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse("logs:topic", args=[topic.id]))
    context = {'topic': topic, 'form': form}
    return render(request, 'edit_topic.html', context)

@login_required
def new_entry(request, topic_id):
    '''Add a new entry for a particular topic'''
    topic = Topic.objects.get(id=topic_id)
    if request.method != 'POST':
        form = EntryForm()
    else:
        form = EntryForm(data = request.POST)
        if form.is_valid():
            new_entry=form.save(commit=False)
            new_entry.topic = topic
            new_entry.save()
            return HttpResponseRedirect(reverse('logs:topic', args=[topic_id]))
    context = {'topic': topic, 'form': form}
    return render(request, 'new_entry.html', context)

@login_required
def edit_entry(request, entry_id):
    '''Edit an existing entry.'''
    entry = Entry.objects.get(id=entry_id)
    topic = entry.topic

    if request.method != 'POST':
        form = EntryForm(instance=entry)
    else:
        form = EntryForm(instance =entry, data=request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse('logs:topic', args=[topic.id]))
    context = {'entry': entry, 'topic': topic, 'form': form}
    return render(request, 'edit_entry.html', context)

@login_required
def delete_entry(request, entry_id):
    '''delete an existng entry.'''
    entry = Entry.objects.get(id=entry_id)
    topic = entry.topic
    entry_to_delete = get_object_or_404(Entry, id=entry_id)

    if request.method!='POST':
        form = DeleteEntryForm(instance=entry)
    else:
        form = DeleteEntryForm(instance=entry,data=request.POST)
        if form.is_valid():
            entry_to_delete.delete()
            return HttpResponseRedirect(reverse('logs:topic', args=[topic.id]))
    context = {'entry': entry, 'topic': topic, 'form': form}
    return render(request, 'delete_entry.html', context)

@login_required
def delete_topic(request, topic_id):
    '''delete an existng topic.'''
    topic = Topic.objects.get(id=topic_id)
    topic_to_delete = get_object_or_404(Topic, id=topic_id)
    if request.method != 'POST':
        form = DeleteTopicForm(instance=topic)
    else:
        form = DeleteTopicForm(instance=topic, data=request.POST)
        if form.is_valid():
            topic_to_delete.delete()
            return HttpResponseRedirect(reverse('logs:topics'))
    context = {'topic': topic, 'form': form}
    return render(request, 'delete_topic.html', context)


import mlflow
import uvicorn
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware

from es.query import search_embeddings
from config import get_settings, Query
from es.conn import create_conn, check_connection

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

# load env variables
settings = get_settings()
source = ["imgUrl", "title", "userId", "userName", "postedOn"]

# create es connection
print(check_connection(settings.es_host, settings.es_port))
es = create_conn(settings.es_host, settings.es_port)

# load model
model = mlflow.pyfunc.load_model(settings.model_path).unwrap_python_model()

# warm up call to model
print(f"warm up model call, embedding size: {len(model.extract_text_embeddings('give me embeddings'))}")

@app.post("/text_search")
async def get_similar_images_text(query: Query):
    if query.phrase is None:
        raise HTTPException(status_code=400, detail="'phrase' is required for text based search")

    emb = model.extract_text_embeddings(query.phrase)
    try:
        res = await search_embeddings(
            es, emb,
            index=settings.es_index,
            source=source,
            page=query.page,
            k=query.rowsPerPage
        )
        return res
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.post("/image_search")
async def get_similar_images(query: Query):
    if query.image is None:
        raise HTTPException(status_code=400, detail="'image' is required for image based search")

    try:
        emb = model.extract_image_embeddings(query.image)
    except Exception as e:
        msg = f"please share a valid URL or upload an image - {str(e).split(':')[0]}"
        raise HTTPException(status_code=500, detail=msg)

    try:
        res = await search_embeddings(
            es, emb,
            index=settings.es_index,
            source=source,
            page=query.page,
            k=query.rowsPerPage
        )
        return res
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

if __name__ == '__main__':
    uvicorn.run(app, host="0.0.0.0", port=80)