import scipy.io as sio
import numpy as np
import keras
import keras.backend as K
from keras.layers import Input, GlobalAveragePooling2D, Reshape, Lambda, Dense, Flatten
from keras.layers.convolutional import Conv2D, ZeroPadding2D, MaxPooling2D, AveragePooling2D
from keras.layers.normalization import BatchNormalization
from keras.layers.core import Lambda, Activation
from keras.models import Model
from keras import optimizers
from keras.callbacks import LearningRateScheduler
import constants as c
import matplotlib.pyplot as plt
from keras import metrics

def euclidean_distance(vects):
    x, y = vects
    sum_square = K.sum(K.square(x - y), axis=1, keepdims=True)
    return K.sqrt(K.maximum(sum_square, K.epsilon()))

def eucl_dist_output_shape(shapes):
    shape1, shape2 = shapes
    return (shape1[0], 1)

# Block of layers: Conv --> BatchNorm --> ReLU --> Pool
def conv_bn_pool(inp_tensor,layer_idx,conv_filters,conv_kernel_size,conv_strides,conv_pad,
	pool='',pool_size=(2, 2),pool_strides=None,
	conv_layer_prefix='conv'):
	x = ZeroPadding2D(padding=conv_pad,name='pad{}'.format(layer_idx))(inp_tensor)
	x = Conv2D(filters=conv_filters,kernel_size=conv_kernel_size, strides=conv_strides, padding='valid', name='{}{}'.format(conv_layer_prefix,layer_idx))(x)
	x = BatchNormalization(epsilon=1e-5,momentum=1,name='bn{}'.format(layer_idx))(x)
	x = Activation('relu', name='relu{}'.format(layer_idx))(x)
	if pool == 'max':
		x = MaxPooling2D(pool_size=pool_size,strides=pool_strides,name='mpool{}'.format(layer_idx))(x)
	elif pool == 'avg':
		x = AveragePooling2D(pool_size=pool_size,strides=pool_strides,name='apool{}'.format(layer_idx))(x)
	return x

# Block of layers: Conv --> BatchNorm --> ReLU --> Dynamic average pool (fc6 -> apool6 only)
def conv_bn_dynamic_apool(inp_tensor,layer_idx,conv_filters,conv_kernel_size,conv_strides,conv_pad,
	conv_layer_prefix='conv'):
	x = ZeroPadding2D(padding=conv_pad,name='pad{}'.format(layer_idx))(inp_tensor)
	x = Conv2D(filters=conv_filters,kernel_size=conv_kernel_size, strides=conv_strides, padding='valid', name='{}{}'.format(conv_layer_prefix,layer_idx))(x)
	x = BatchNormalization(epsilon=1e-5,momentum=1,name='bn{}'.format(layer_idx))(x)
	x = Activation('relu', name='relu{}'.format(layer_idx))(x)
	x = GlobalAveragePooling2D(name='gapool{}'.format(layer_idx))(x)
	x = Reshape((1,1,conv_filters),name='reshape{}'.format(layer_idx))(x)
	return x

def vggvox_model():
	inp = Input(c.INPUT_SHAPE,name='input')
	x = conv_bn_pool(inp,layer_idx=1,conv_filters=96,conv_kernel_size=(7,7),conv_strides=(2,2),conv_pad=(1,1),
		pool='max',pool_size=(3,3),pool_strides=(2,2))
	x = conv_bn_pool(x,layer_idx=2,conv_filters=256,conv_kernel_size=(5,5),conv_strides=(2,2),conv_pad=(1,1),
		pool='max',pool_size=(3,3),pool_strides=(2,2))
	x = conv_bn_pool(x,layer_idx=3,conv_filters=384,conv_kernel_size=(3,3),conv_strides=(1,1),conv_pad=(1,1))
	x = conv_bn_pool(x,layer_idx=4,conv_filters=256,conv_kernel_size=(3,3),conv_strides=(1,1),conv_pad=(1,1))
	x = conv_bn_pool(x,layer_idx=5,conv_filters=256,conv_kernel_size=(3,3),conv_strides=(1,1),conv_pad=(1,1),
		pool='max',pool_size=(5,3),pool_strides=(3,2))
	x = conv_bn_dynamic_apool(x,layer_idx=6,conv_filters=4096,conv_kernel_size=(9,1),conv_strides=(1,1),conv_pad=(0,0),
		conv_layer_prefix='fc')
	x = conv_bn_pool(x,layer_idx=7,conv_filters=1024,conv_kernel_size=(1,1),conv_strides=(1,1),conv_pad=(0,0),
		conv_layer_prefix='fc')
	x = Lambda(lambda y: K.l2_normalize(y, axis=3), name='norm')(x)  #L2-normalization
	x = Conv2D(filters=1024,kernel_size=(1,1), strides=(1,1), padding='valid', name='fc8')(x)

	m = Model(inp, x, name='VGGVox')
	# print("*"*10, m.input_shape)
	return m

def siamese_network(input_shape, model):

	input_a = Input(shape=input_shape)
	input_b = Input(shape=input_shape)

	# network definition
	base_network = vggvox_mod_model(model)
	# because we re-use the same instance `base_network`,
	# the weights of the network
	# will be shared across the two branches
	processed_a = base_network(input_a)
	processed_b = base_network(input_b)

	distance = Lambda(euclidean_distance,
					output_shape=eucl_dist_output_shape)([processed_a, processed_b])

	model = Model([input_a, input_b], distance, name='Siamese')

	return model

def vggvox_mod_model(model):
	for layer in model.layers[:-1]:
		layer.trainable = False

	# # Check the trainable status of the individual layers
	# for layer in model.layers:
	# 	print(layer, layer.trainable)

	#hidden layers part
	model.layers.pop()  #pop last layer
	conv_layer = Conv2D(filters=256,kernel_size=(1,1), strides=(1,1), padding='valid', name='fc8')  #final fc layer reduced to 256

	inp = model.input
	out = conv_layer(model.layers[-1].output)

	#classification part
	fc9 = Dense(c.NUM_CLASSES, activation='softmax', name='fc9')
	out =  Flatten()(out)
	out = fc9 (out)

	model2 = Model(inp, out, name='VGG-M')

	return model2

#define step decay function
class LossHistory_(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        self.losses = []
        self.lr = []

    def on_epoch_end(self, batch, logs={}):
        self.losses.append(logs.get('loss'))
        self.lr.append(exp_decay(len(self.losses)))
        print('lr:', exp_decay(len(self.losses)))

def exp_decay(epoch):
    initial_lrate = 1e-2
    k = 1e-8
    lrate = initial_lrate * np.exp(-k*epoch)
    return lrate

def plot_fig(i, history):
    fig = plt.figure()
    # plt.plot(range(1,c.EPOCHS+1),history.history['val_acc'],label='validation')
    plt.plot(range(1,c.EPOCHS+1),history.history['acc'],label='training')
    plt.legend(loc=0)
    plt.xlabel('epochs')
    plt.ylabel('accuracy')
    plt.xlim([1,c.EPOCHS])
#   plt.ylim([0,1])
    plt.grid(True)
    plt.title("Model Accuracy")
    plt.show()
    fig.savefig('img/'+str(i)+'-accuracy.jpg')
    plt.close(fig)

def contrastive_loss(y_true, y_pred):
    '''Contrastive loss from Hadsell-et-al.'06
    http://yann.lecun.com/exdb/publis/pdf/hadsell-chopra-lecun-06.pdf
    '''
    margin = 1
    square_pred = K.square(y_pred)
    margin_square = K.square(K.maximum(margin - y_pred, 0))
    return K.mean(y_true * square_pred + (1 - y_true) * margin_square)

def compute_accuracy(y_true, y_pred):
    '''Compute classification accuracy with a fixed threshold on distances.
    '''
    pred = y_pred.ravel() < 0.5
    return np.mean(pred == y_true)

def accuracy(y_true, y_pred):
    '''Compute classification accuracy with a fixed threshold on distances.
    '''
    return K.mean(K.equal(y_true, K.cast(y_pred < 0.5, y_true.dtype)))

def train_siamese(model, tr_pairs, tr_y):
	# define SGD optimizer
	sgd = optimizers.SGD(lr=0.00, decay=c.WEIGHT_DECAY, momentum=c.SGD_MOMENTUM, nesterov=True)
	model.compile(loss=contrastive_loss, optimizer=sgd, metrics=[accuracy])

	# compile the model
	# learning schedule callback
	loss_history_ = LossHistory_()
	lrate_ = LearningRateScheduler(exp_decay)
	callbacks_list_ = [loss_history_, lrate_]

	# fit the model
	print("tr_pairs 0 shape {}, tr_pairs 1 {}".format(tr_pairs[:, 0].shape, tr_pairs[:, 1].shape))
	history = model.fit([tr_pairs[:, 0], tr_pairs[:, 1]], tr_y,
		validation_split=0.1,
		epochs=c.EPOCHS,
		batch_size=c.BATCH_SIZE,
		callbacks=callbacks_list_)

	# Save the model
	weights_file = model.name + '_weights.h5'
	model.save(weights_file)

	# plot model accuracy
	# plot_fig(model.name, history)

	return model

def top_1_categorical_accuracy(y_true, y_pred):
    return metrics.top_k_categorical_accuracy(y_true, y_pred, k=1)

def top_5_categorical_accuracy(y_true, y_pred):
    return metrics.top_k_categorical_accuracy(y_true, y_pred, k=5)

def compile_model(model):
	# define SGD optimizer
	sgd = optimizers.SGD(lr=0.00, decay=c.WEIGHT_DECAY, momentum=c.SGD_MOMENTUM, nesterov=True)
	model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=[top_1_categorical_accuracy,top_5_categorical_accuracy])

	return model

def train_for_classification(model, tr_X, tr_y):
	# learning schedule callback
	loss_history_ = LossHistory_()
	lrate_ = LearningRateScheduler(exp_decay)
	callbacks_list_ = [loss_history_, lrate_]

	# fit the model
	history = model.fit(tr_X, tr_y,
		validation_split=0.1,
		epochs=c.EPOCHS,
		batch_size=c.BATCH_SIZE,
		callbacks=callbacks_list_)

	print(history.history)

	# Save the model
	weights_file = model.name + '_weights.h5'
	model.save(weights_file)

	# # plot model accuracy
	# plot_fig(model.name, history)

	return model

def test():
	model = vggvox_model()
	num_layers = len(model.layers)

	x = np.random.randn(1,512,30,1)
	outputs = []

	for i in range(num_layers):
		get_ith_layer_output = K.function([model.layers[0].input, K.learning_phase()],
		                              [model.layers[i].output])
		layer_output = get_ith_layer_output([x, 0])[0] 	# output in test mode = 0
		outputs.append(layer_output)

	for i in range(11):
		print("Shape of layer {} output:{}".format(i, outputs[i].shape))

if __name__ == '__main__':
	test()


from flask import Flask, render_template, request

from base64 import b64decode, b64encode
import cv2
import io
import json

import requests
import numpy as np

app = Flask(__name__)

def preprocess_image(image_file_path, max_width, max_height):
    """Preprocesses input images for AutoML Vision Edge models.

    Args:
        image_file_path: Path to a local image for the prediction request.
        max_width: The max width for preprocessed images. The max width is 640
            (1024) for AutoML Vision Image Classfication (Object Detection)
            models.
        max_height: The max width for preprocessed images. The max height is
            480 (1024) for AutoML Vision Image Classfication (Object
            Detetion) models.
    Returns:
        The preprocessed encoded image bytes.
    """
    # cv2 is used to read, resize and encode images.
    encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 85]
    # im = cv2.imread(image_file_path)
    # im=request.files.get('image')
    # im = cv2.imdecode(np.frombuffer(io_buf.getbuffer(), np.uint8), -1)
    im=image_file_path
    [height, width, _] = im.shape
    if height > max_height or width > max_width:
        ratio = max(height / float(max_width), width / float(max_height))
        new_height = int(height / ratio + 0.5)
        new_width = int(width / ratio + 0.5)
        resized_im = cv2.resize(
            im, (new_width, new_height), interpolation=cv2.INTER_AREA)
        _, processed_image = cv2.imencode('.jpg', resized_im, encode_param)
    else:
        _, processed_image = cv2.imencode('.jpg', im, encode_param)

    print("imagepreprocessed")
    return b64encode(processed_image).decode('utf-8')

def container_predict(image_file_path, image_key, port_number=8501):
    """Sends a prediction request to TFServing docker container REST API.

    Args:
        image_file_path: Path to a local image for the prediction request.
        image_key: Your chosen string key to identify the given image.
        port_number: The port number on your device to accept REST API calls.
    Returns:
        The response of the prediction request.
    """
    # AutoML Vision Edge models will preprocess the input images.
    # The max width and height for AutoML Vision Image Classification and
    # Object Detection models are 640*480 and 1024*1024 separately. The
    # example here is for Image Classification models.
    encoded_image = preprocess_image(
        image_file_path=image_file_path, max_width=640, max_height=480)

    # The example here only shows prediction with one image. You can extend it
    # to predict with a batch of images indicated by different keys, which can
    # make sure that the responses corresponding to the given image.
    # instances = {
    #         'instances': [
    #                 {'image_bytes': {'b64': str(encoded_image)},
    #                  'key': image_key}
    #         ]
    # }
    #
    # # This example shows sending requests in the same server that you start
    # # docker containers. If you would like to send requests to other servers,
    # # please change localhost to IP of other servers.
    # url = 'http://0.0.0.0:{}/v1/models/default:predict'.format(port_number)
    #
    # response = requests.post(url, data=json.dumps(instances))
    #
    # response1 = json.loads(response.content)

    payload = {
        'instances': [
            {'image_bytes': {'b64': str(encoded_image)},
             'key': image_key}
        ]
    }

    # This example shows sending requests in the same server that you start
    # docker containers. If you would like to send requests to other servers,
    # please change localhost to IP of other servers.
    url = 'http://0.0.0.0:{}/v1/models/default:predict'.format(port_number)
    url = 'https://dog-classifier-x2cqll44ga-ew.a.run.app/v1/models/default:predict'
    response = requests.post(url, data=json.dumps(payload))
    print("here")
    # print(response.content)
    # print(type(response.content))
    response1 = json.loads(response.content)

    x = response1["predictions"][0]["scores"]
    max_value = max(x)
    max_index = x.index(max_value)
    breed = response1["predictions"][0]["labels"][max_index]

    print(type(x))
    print(x)
    print(breed)
    return breed

# def predict_label(img_path):
#     i = image.load_img(img_path, target_size=(100,100))
# 	i = image.img_to_array(i)/255.0
# 	i = i.reshape(1, 100,100,3)
# 	p = model.predict_classes(i)
# 	return dic[p[0]]

# routes
@app.route("/", methods=['GET', 'POST'])
def main():
    return render_template("index.html")

@app.route("/about")
def about_page():
    return "Please subscribe  Artificial Intelligence Hub..!!!"

@app.route("/submit", methods = ['GET', 'POST'])
def get_output():
    if request.method == 'POST':
        img = request.files['my_image']
        imgr=img.read()
        img_b64 = b64encode(imgr).decode()
        img_src = 'data:{};base64,{}'.format(img.content_type, img_b64)
        npimg = np.fromstring(imgr, np.uint8)
        img = cv2.imdecode(npimg, cv2.IMREAD_UNCHANGED)
        # p = container_predict(img, "1", 8501)

        # img_path = "tmp/" + img.filename
        # img.save(img_path)
        img_path=img
        print(type(img_path))

        p= container_predict(img_path,"1",8501)
        # p = predict_label(img_path)

    return render_template("index.html", prediction = p, img_path = img_src)

if __name__ =='__main__':
    #app.debug = True
    app.run(host='0.0.0.0', port=5000)


from __future__ import annotations

__all__ = [
    "BasePeriodicTimeSeriesGenerator",
    "is_periodic_timeseries_generator_config",
    "setup_periodic_timeseries_generator",
]

import logging
from abc import ABC, abstractmethod

from objectory import AbstractFactory
from objectory.utils import is_object_config
from redcat import BatchDict
from torch import Generator

from startorch.utils.format import str_target_object

logger = logging.getLogger(__name__)

class BasePeriodicTimeSeriesGenerator(ABC, metaclass=AbstractFactory):
    r"""Defines the base class to generate periodic time series.

    A child class has to implement the ``generate`` method.

    Example usage:

    .. code-block:: pycon

        Example usage:

    .. code-block:: pycon

        >>> from startorch.periodic.timeseries import Repeat
        >>> from startorch.timeseries import TimeSeries
        >>> from startorch.sequence import RandUniform
        >>> generator = Repeat(TimeSeries({"value": RandUniform(), "time": RandUniform()}))
        >>> generator
        RepeatPeriodicTimeSeriesGenerator(
          (generator): TimeSeriesGenerator(
              (value): RandUniformSequenceGenerator(low=0.0, high=1.0, feature_size=(1,))
              (time): RandUniformSequenceGenerator(low=0.0, high=1.0, feature_size=(1,))
            )
        )
        >>> generator.generate(seq_len=12, period=4, batch_size=4)
        BatchDict(
          (value): tensor([[...]], batch_dim=0, seq_dim=1)
          (time): tensor([[...]], batch_dim=0, seq_dim=1)
        )
    """

    @abstractmethod
    def generate(
        self, seq_len: int, period: int, batch_size: int = 1, rng: Generator | None = None
    ) -> BatchDict:
        r"""Generates a batch of periodic time series.

        All the time series in the batch have the same length.

        Args:
        ----
            seq_len (int): Specifies the sequence length.
            period (int): Specifies the period.
            batch_size (int, optional): Specifies the batch size.
                Default: ``1``
            rng (``torch.Generator`` or None, optional): Specifies
                an optional random number generator. Default: ``None``

        Returns:
        -------
            ``BatchDict``: A batch of periodic time series.

        Example usage:

        .. code-block:: pycon

            >>> from startorch.periodic.timeseries import Repeat
            >>> from startorch.timeseries import TimeSeries
            >>> from startorch.sequence import RandUniform
            >>> generator = Repeat(TimeSeries({"value": RandUniform(), "time": RandUniform()}))
            >>> generator.generate(seq_len=12, period=4, batch_size=4)
            BatchDict(
              (value): tensor([[...]], batch_dim=0, seq_dim=1)
              (time): tensor([[...]], batch_dim=0, seq_dim=1)
            )
        """

def is_periodic_timeseries_generator_config(config: dict) -> bool:
    r"""Indicates if the input configuration is a configuration for a
    ``BasePeriodicTimeSeriesGenerator``.

    This function only checks if the value of the key  ``_target_``
    is valid. It does not check the other values. If ``_target_``
    indicates a function, the returned type hint is used to check
    the class.

    Args:
    ----
        config (dict): Specifies the configuration to check.

    Returns:
    -------
        bool: ``True`` if the input configuration is a configuration
            for a ``BasePeriodicTimeSeriesGenerator`` object.

    Example usage:

    .. code-block:: pycon

        >>> from startorch.periodic.timeseries import is_periodic_timeseries_generator_config
        >>> is_periodic_timeseries_generator_config(
        ...     {
        ...         "_target_": "startorch.periodic.timeseries.Repeat",
        ...         "generator": {
        ...             "_target_": "startorch.timeseries.TimeSeries",
        ...             "sequences": {
        ...                 "value": {"_target_": "startorch.sequence.RandUniform"},
        ...                 "time": {"_target_": "startorch.sequence.RandUniform"},
        ...             },
        ...         },
        ...     }
        ... )
        True
    """
    return is_object_config(config, BasePeriodicTimeSeriesGenerator)

def setup_periodic_timeseries_generator(
    generator: BasePeriodicTimeSeriesGenerator | dict,
) -> BasePeriodicTimeSeriesGenerator:
    r"""Sets up a periodic time series generator.

    The time series generator is instantiated from its configuration by
    using the ``BasePeriodicTimeSeriesGenerator`` factory function.

    Args:
    ----
        generator (``BasePeriodicTimeSeriesGenerator`` or dict): Specifies a
            periodic time series generator or its configuration.

    Returns:
    -------
        ``BasePeriodicTimeSeriesGenerator``: A periodic time series generator.

    Example usage:

    .. code-block:: pycon

        >>> from startorch.periodic.timeseries import setup_periodic_timeseries_generator
        >>> setup_periodic_timeseries_generator(
        ...     {
        ...         "_target_": "startorch.periodic.timeseries.Repeat",
        ...         "generator": {
        ...             "_target_": "startorch.timeseries.TimeSeries",
        ...             "sequences": {
        ...                 "value": {"_target_": "startorch.sequence.RandUniform"},
        ...                 "time": {"_target_": "startorch.sequence.RandUniform"},
        ...             },
        ...         },
        ...     }
        ... )
        RepeatPeriodicTimeSeriesGenerator(
          (generator): TimeSeriesGenerator(
              (value): RandUniformSequenceGenerator(low=0.0, high=1.0, feature_size=(1,))
              (time): RandUniformSequenceGenerator(low=0.0, high=1.0, feature_size=(1,))
            )
        )
    """
    if isinstance(generator, dict):
        logger.info(
            "Initializing a periodic time series generator from its configuration... "
            f"{str_target_object(generator)}"
        )
        generator = BasePeriodicTimeSeriesGenerator.factory(**generator)
    if not isinstance(generator, BasePeriodicTimeSeriesGenerator):
        logger.warning(
            f"generator is not a `BasePeriodicTimeSeriesGenerator` (received: {type(generator)})"
        )
    return generator


import datetime
from typing import TYPE_CHECKING, Any, Dict, List, Type, TypeVar, Union

import attr
from dateutil.parser import isoparse

from ..models.access_right_item_data_granted_item_type import AccessRightItemDataGrantedItemType
from ..types import UNSET, Unset

if TYPE_CHECKING:
    from ..models.access_right_item_data_granted_data import AccessRightItemDataGrantedData

T = TypeVar("T", bound="AccessRightItemDataGranted")

@attr.s(auto_attribs=True)
class AccessRightItemDataGranted:
    """
    Attributes:
        access_granted (Union[Unset, bool]): flag indicating if access is granted
        life_time_start (Union[Unset, datetime.datetime]): date the access right will start with date-time notation as
            defined by RFC 3339, section 5.6,
            for example, 2017-07-21T17:32:28Z
        life_time_end (Union[Unset, datetime.datetime]): date the access right will end with date-time notation as
            defined by RFC 3339, section 5.6,
            for example, 2017-07-21T17:32:28Z
        access_time_start (Union[Unset, datetime.datetime]): time the access right will start with time notation as
            defined by RFC 3339, section 5.6,
            for example, 17:32:28
        access_time_end (Union[Unset, datetime.datetime]): time the access right will end with time notation as defined
            by RFC 3339, section 5.6, for
            example, 17:32:28
        pause_time_start (Union[Unset, datetime.datetime]): start date the access right will paused with date-time
            notation as defined by RFC 3339,
            section 5.6, for example, 2017-07-21T17:32:28Z
        pause_time_end (Union[Unset, datetime.datetime]): end date the access right pause end with date-time notation as
            defined by RFC 3339, section 5.6,
            for example, 2017-07-21T17:32:28Z
        max_cache_date (Union[Unset, datetime.datetime]): max cache date with date-time notation as defined by RFC 3339, section 5.6, for example,
            2017-07-21T17:32:28Z
        data (Union[Unset, AccessRightItemDataGrantedData]):
        blocked (Union[Unset, bool]): flag indicating if access is blocked
        product_id (Union[Unset, str]): id of the product bought
        plenigo_offer_id (Union[Unset, str]): if the product is based on a plenigo offer the plenigo offer id is
            provided here
        plenigo_product_id (Union[Unset, str]): if the product is based on a plenigo offer the plenigo product id is
            provided here - can be identically to the productId
        plenigo_step_id (Union[Unset, str]): if the product is based on a plenigo offer the plenigo step id is provided
            here
        access_right_unique_id (Union[Unset, str]): unique id of the access right this order item grants access to
        item_type (Union[Unset, AccessRightItemDataGrantedItemType]): type of this access right item
        item_id (Union[Unset, str]): the id this access right belongs to
    """

    access_granted: Union[Unset, bool] = UNSET
    life_time_start: Union[Unset, datetime.datetime] = UNSET
    life_time_end: Union[Unset, datetime.datetime] = UNSET
    access_time_start: Union[Unset, datetime.datetime] = UNSET
    access_time_end: Union[Unset, datetime.datetime] = UNSET
    pause_time_start: Union[Unset, datetime.datetime] = UNSET
    pause_time_end: Union[Unset, datetime.datetime] = UNSET
    max_cache_date: Union[Unset, datetime.datetime] = UNSET
    data: Union[Unset, "AccessRightItemDataGrantedData"] = UNSET
    blocked: Union[Unset, bool] = UNSET
    product_id: Union[Unset, str] = UNSET
    plenigo_offer_id: Union[Unset, str] = UNSET
    plenigo_product_id: Union[Unset, str] = UNSET
    plenigo_step_id: Union[Unset, str] = UNSET
    access_right_unique_id: Union[Unset, str] = UNSET
    item_type: Union[Unset, AccessRightItemDataGrantedItemType] = UNSET
    item_id: Union[Unset, str] = UNSET
    additional_properties: Dict[str, Any] = attr.ib(init=False, factory=dict)

    def to_dict(self) -> Dict[str, Any]:
        access_granted = self.access_granted
        life_time_start: Union[Unset, str] = UNSET
        if not isinstance(self.life_time_start, Unset):
            life_time_start = self.life_time_start.isoformat()

        life_time_end: Union[Unset, str] = UNSET
        if not isinstance(self.life_time_end, Unset):
            life_time_end = self.life_time_end.isoformat()

        access_time_start: Union[Unset, str] = UNSET
        if not isinstance(self.access_time_start, Unset):
            access_time_start = self.access_time_start.isoformat()

        access_time_end: Union[Unset, str] = UNSET
        if not isinstance(self.access_time_end, Unset):
            access_time_end = self.access_time_end.isoformat()

        pause_time_start: Union[Unset, str] = UNSET
        if not isinstance(self.pause_time_start, Unset):
            pause_time_start = self.pause_time_start.isoformat()

        pause_time_end: Union[Unset, str] = UNSET
        if not isinstance(self.pause_time_end, Unset):
            pause_time_end = self.pause_time_end.isoformat()

        max_cache_date: Union[Unset, str] = UNSET
        if not isinstance(self.max_cache_date, Unset):
            max_cache_date = self.max_cache_date.isoformat()

        data: Union[Unset, Dict[str, Any]] = UNSET
        if not isinstance(self.data, Unset):
            data = self.data.to_dict()

        blocked = self.blocked
        product_id = self.product_id
        plenigo_offer_id = self.plenigo_offer_id
        plenigo_product_id = self.plenigo_product_id
        plenigo_step_id = self.plenigo_step_id
        access_right_unique_id = self.access_right_unique_id
        item_type: Union[Unset, str] = UNSET
        if not isinstance(self.item_type, Unset):
            item_type = self.item_type.value

        item_id = self.item_id

        field_dict: Dict[str, Any] = {}
        field_dict.update(self.additional_properties)
        field_dict.update({})
        if access_granted is not UNSET:
            field_dict["accessGranted"] = access_granted
        if life_time_start is not UNSET:
            field_dict["lifeTimeStart"] = life_time_start
        if life_time_end is not UNSET:
            field_dict["lifeTimeEnd"] = life_time_end
        if access_time_start is not UNSET:
            field_dict["accessTimeStart"] = access_time_start
        if access_time_end is not UNSET:
            field_dict["accessTimeEnd"] = access_time_end
        if pause_time_start is not UNSET:
            field_dict["pauseTimeStart"] = pause_time_start
        if pause_time_end is not UNSET:
            field_dict["pauseTimeEnd"] = pause_time_end
        if max_cache_date is not UNSET:
            field_dict["maxCacheDate"] = max_cache_date
        if data is not UNSET:
            field_dict["data"] = data
        if blocked is not UNSET:
            field_dict["blocked"] = blocked
        if product_id is not UNSET:
            field_dict["productId"] = product_id
        if plenigo_offer_id is not UNSET:
            field_dict["plenigoOfferId"] = plenigo_offer_id
        if plenigo_product_id is not UNSET:
            field_dict["plenigoProductId"] = plenigo_product_id
        if plenigo_step_id is not UNSET:
            field_dict["plenigoStepId"] = plenigo_step_id
        if access_right_unique_id is not UNSET:
            field_dict["accessRightUniqueId"] = access_right_unique_id
        if item_type is not UNSET:
            field_dict["itemType"] = item_type
        if item_id is not UNSET:
            field_dict["itemId"] = item_id

        return field_dict

    @classmethod
    def from_dict(cls: Type[T], src_dict: Dict[str, Any]) -> T:
        from ..models.access_right_item_data_granted_data import AccessRightItemDataGrantedData

        d = src_dict.copy()
        access_granted = d.pop("accessGranted", UNSET)

        _life_time_start = d.pop("lifeTimeStart", UNSET)
        life_time_start: Union[Unset, datetime.datetime]
        if isinstance(_life_time_start, Unset):
            life_time_start = UNSET
        else:
            life_time_start = isoparse(_life_time_start)

        _life_time_end = d.pop("lifeTimeEnd", UNSET)
        life_time_end: Union[Unset, datetime.datetime]
        if isinstance(_life_time_end, Unset):
            life_time_end = UNSET
        else:
            life_time_end = isoparse(_life_time_end)

        _access_time_start = d.pop("accessTimeStart", UNSET)
        access_time_start: Union[Unset, datetime.datetime]
        if isinstance(_access_time_start, Unset):
            access_time_start = UNSET
        else:
            access_time_start = isoparse(_access_time_start)

        _access_time_end = d.pop("accessTimeEnd", UNSET)
        access_time_end: Union[Unset, datetime.datetime]
        if isinstance(_access_time_end, Unset):
            access_time_end = UNSET
        else:
            access_time_end = isoparse(_access_time_end)

        _pause_time_start = d.pop("pauseTimeStart", UNSET)
        pause_time_start: Union[Unset, datetime.datetime]
        if isinstance(_pause_time_start, Unset):
            pause_time_start = UNSET
        else:
            pause_time_start = isoparse(_pause_time_start)

        _pause_time_end = d.pop("pauseTimeEnd", UNSET)
        pause_time_end: Union[Unset, datetime.datetime]
        if isinstance(_pause_time_end, Unset):
            pause_time_end = UNSET
        else:
            pause_time_end = isoparse(_pause_time_end)

        _max_cache_date = d.pop("maxCacheDate", UNSET)
        max_cache_date: Union[Unset, datetime.datetime]
        if isinstance(_max_cache_date, Unset):
            max_cache_date = UNSET
        else:
            max_cache_date = isoparse(_max_cache_date)

        _data = d.pop("data", UNSET)
        data: Union[Unset, AccessRightItemDataGrantedData]
        if isinstance(_data, Unset):
            data = UNSET
        else:
            data = AccessRightItemDataGrantedData.from_dict(_data)

        blocked = d.pop("blocked", UNSET)

        product_id = d.pop("productId", UNSET)

        plenigo_offer_id = d.pop("plenigoOfferId", UNSET)

        plenigo_product_id = d.pop("plenigoProductId", UNSET)

        plenigo_step_id = d.pop("plenigoStepId", UNSET)

        access_right_unique_id = d.pop("accessRightUniqueId", UNSET)

        _item_type = d.pop("itemType", UNSET)
        item_type: Union[Unset, AccessRightItemDataGrantedItemType]
        if isinstance(_item_type, Unset):
            item_type = UNSET
        else:
            item_type = AccessRightItemDataGrantedItemType(_item_type)

        item_id = d.pop("itemId", UNSET)

        access_right_item_data_granted = cls(
            access_granted=access_granted,
            life_time_start=life_time_start,
            life_time_end=life_time_end,
            access_time_start=access_time_start,
            access_time_end=access_time_end,
            pause_time_start=pause_time_start,
            pause_time_end=pause_time_end,
            max_cache_date=max_cache_date,
            data=data,
            blocked=blocked,
            product_id=product_id,
            plenigo_offer_id=plenigo_offer_id,
            plenigo_product_id=plenigo_product_id,
            plenigo_step_id=plenigo_step_id,
            access_right_unique_id=access_right_unique_id,
            item_type=item_type,
            item_id=item_id,
        )

        access_right_item_data_granted.additional_properties = d
        return access_right_item_data_granted

    @property
    def additional_keys(self) -> List[str]:
        return list(self.additional_properties.keys())

    def __getitem__(self, key: str) -> Any:
        return self.additional_properties[key]

    def __setitem__(self, key: str, value: Any) -> None:
        self.additional_properties[key] = value

    def __delitem__(self, key: str) -> None:
        del self.additional_properties[key]

    def __contains__(self, key: str) -> bool:
        return key in self.additional_properties


import os

from model import *
from data import test_generator
from utils import create_directory, get_subfiles
from show_annotated_images import save_images_and_masks, save_result

from dotenv import load_dotenv
load_dotenv()

# TEST
def get_predictions():
    create_directory(os.getenv('PREDICTION_IMAGES_PATH'))

    test_filenames = get_subfiles(os.getenv('PNG_IMAGES_PATH'))

    weight_file_path = os.getenv('MODELPATH')

    model = unet(pretrained_weights=weight_file_path)

    testgen = test_generator(os.getenv('PNG_IMAGES_PATH'))

    test_batch_size = len(test_filenames)

    print('\nStarting testing ...\n')
    print('Using model - {}\n'.format(weight_file_path))
    results = model.predict_generator(testgen, test_batch_size, verbose=1)
    print('DONE !')

    # save predictions - images and masks
    print('\nSaving test results - masks')
    save_result(os.getenv('PREDICTION_IMAGES_PATH'), results, test_filenames, flag_multi_class=False, num_class=2)
    print('DONE !')

    if os.getenv('SAVE_COMBINED') == 'TRUE':
        create_directory(os.getenv('COMBINED_IMAGES_PATH'))
        imagesdir = os.getenv('PNG_IMAGES_PATH')
        masksdir = os.getenv('PREDICTION_IMAGES_PATH')
        suffix = '_predict'

        print('\nSaving test results - images and masks combined')
        save_images_and_masks(imagesdir, masksdir, suffix, save=True)
        print('DONE !')


from fastapi import FastAPI
from pydantic import BaseModel,Field
from typing import Optional
from uuid import UUID

app = FastAPI()

class Book(BaseModel):
    id:UUID
    title: str = Field(min_length=1) # Data validation
    author: str = Field(min_length=1,max_length=100)
    description: Optional[str] = Field(title="Description of the book",min_length = 1,max_length=100)
    rating : int = Field(gt=-1,lt=101)

Books = []

@app.get("/")
async def read_all_books():
    if len(Books)<=0:
        create_books_no_api()
    return Books

@app.post("/createbook")
async def create_book(book:Book):
    Books.append(book)
    return book

#How to add books to book list when BOOKS list is empty

def create_books_no_api():
    book1 = Book(id="7adfeeec-6a3f-437a-8d19-2743c4edb9f4",
    title = "Computers",
    author = "Charless",
    description= "Description1",
    rating= 90)
    book2 = Book(id="7adfeeec-6a3f-437a-8d19-2743c4edb9f5",
    title = "Maths",
    author = "Venkat",
    description= "Description1",
    rating= 99)
    book3 = Book(id="7adfeeec-6a3f-437a-8d19-2743c4edb9f6",
    title = "Python",
    author = "GVANR",
    description= "Description1",
    rating= 100)

    Books.append(book1)
    Books.append(book2)
    Books.append(book3)

# Get books by passing UUID
@app.get("/books/book_id")
async  def read_book_by_id(book_id:UUID):
    for x in Books:
        if x.id == book_id:
            return x
    return {"Message":"UUID not matched"}

# update book by passing id
@app.put("/{book_id}")
async  def update_book(book_id:UUID,book:Book):
    count =0
    for x in Books:
        count += 1
        if x.id == book_id:
            Books[count-1] = book
        return Books[count-1]

# Delete book
@app.delete("/{book_id}")
async def delete_book(book_id:UUID):
    counter =0
    for x in Books:
        counter +=1
        if x.id == book_id:
            del Books[counter -1]
            return f'Deleted book id is {x.id}'


"""Tests for dials.merge command line program."""

from __future__ import annotations

import json
import shutil
import subprocess

import pytest

from cctbx import uctbx
from dxtbx.serialize import load
from iotbx import mtz

from dials.array_family import flex

def validate_mtz(mtz_file, expected_labels, unexpected_labels=None):
    assert mtz_file.is_file()
    m = mtz.object(str(mtz_file))

    assert m.as_miller_arrays()[1].info().wavelength == pytest.approx(0.6889)
    labels = set()
    for ma in m.as_miller_arrays(merge_equivalents=False):
        labels.update(ma.info().labels)
    for l in expected_labels:
        assert l in labels
    if unexpected_labels:
        for l in unexpected_labels:
            assert l not in labels

@pytest.mark.parametrize("anomalous", [True, False])
@pytest.mark.parametrize(
    "truncate,french_wilson_impl", [(True, "dials"), (True, "cctbx"), (False, None)]
)
def test_merge(dials_data, tmp_path, anomalous, truncate, french_wilson_impl):
    """Test the command line script with LCY data"""
    # Main options: truncate on/off, anomalous on/off
    # french_wilson.implementation dials/cctbx

    r_free_labels = ["FreeR_flag"]
    mean_labels = ["IMEAN", "SIGIMEAN"]
    anom_labels = ["I(+)", "I(-)", "SIGI(+)", "SIGI(-)"]
    amp_labels = ["F", "SIGF"]
    anom_amp_labels = ["F(+)", "SIGF(+)", "F(-)", "SIGF(-)", "DANO", "SIGDANO"]
    half_labels = [
        "IHALF1",
        "SIGIHALF1",
        "IHALF2",
        "SIGIHALF2",
        "NHALF1",
        "NHALF2",
    ]  # appear for additional_stats=True

    location = dials_data("l_cysteine_4_sweeps_scaled", pathlib=True)
    refls = location / "scaled_20_25.refl"
    expts = location / "scaled_20_25.expt"

    mtz_file = tmp_path / f"merge-{anomalous}-{truncate}.mtz"

    command = [
        shutil.which("dials.merge"),
        refls,
        expts,
        f"truncate={truncate}",
        f"french_wilson.implementation={french_wilson_impl}",
        f"anomalous={anomalous}",
        f"output.mtz={str(mtz_file)}",
        "project_name=ham",
        "crystal_name=jam",
        "dataset_name=spam",
        "json=dials.merge.json",
        "additional_stats=True",
    ]
    result = subprocess.run(command, cwd=tmp_path, capture_output=True)
    assert not result.returncode and not result.stderr
    assert (tmp_path / "dials.merge.html").is_file()
    merge_json = tmp_path / "dials.merge.json"
    assert merge_json.is_file()
    expected_labels = mean_labels + half_labels + r_free_labels
    unexpected_labels = []

    with merge_json.open() as fh:
        json_d = json.load(fh)
        wl = list(json_d.keys())[0]
        for k in {"merging_stats", "merging_stats_anom"}:
            assert k in json_d[wl]
            assert {"d_star_sq_min", "n_obs", "cc_anom", "r_split"} <= json_d[wl][
                k
            ].keys()

    if truncate:
        expected_labels += amp_labels
    else:
        unexpected_labels += amp_labels

    if anomalous:
        expected_labels += anom_labels
    else:
        unexpected_labels += anom_labels

    if anomalous and truncate:
        expected_labels += anom_amp_labels
    else:
        unexpected_labels += anom_amp_labels

    validate_mtz(mtz_file, expected_labels, unexpected_labels)

@pytest.mark.parametrize("best_unit_cell", [None, "5.5,8.1,12.0,90,90,90"])
def test_merge_dmin_dmax(dials_data, tmp_path, best_unit_cell):
    """Test the d_min, d_max"""

    location = dials_data("l_cysteine_4_sweeps_scaled", pathlib=True)
    refls = location / "scaled_20_25.refl"
    expts = location / "scaled_20_25.expt"

    mtz_file = tmp_path / "merge.mtz"

    command = [
        shutil.which("dials.merge"),
        refls,
        expts,
        "truncate=False",
        "anomalous=False",
        "d_min=1.0",
        "d_max=8.0",
        f"output.mtz={str(mtz_file)}",
        "project_name=ham",
        "crystal_name=jam",
        "dataset_name=spam",
        f"best_unit_cell={best_unit_cell}",
        "output.html=None",
    ]
    result = subprocess.run(command, cwd=tmp_path, capture_output=True)
    assert not result.returncode and not result.stderr

    # check the unit cell was correctly set if using best_unit_cell
    m = mtz.object(str(mtz_file))
    if best_unit_cell:
        for ma in m.as_miller_arrays():
            assert uctbx.unit_cell(best_unit_cell).parameters() == pytest.approx(
                ma.unit_cell().parameters()
            )

    # check we only have reflections in range 8 - 1A
    max_min_resolution = m.max_min_resolution()

    assert max_min_resolution[0] <= 8
    assert max_min_resolution[1] >= 1

def test_merge_multi_wavelength(dials_data, tmp_path):
    """Test that merge handles multi-wavelength data suitably - should be
    exported into an mtz with separate columns for each wavelength."""

    r_free_labels = ["FreeR_flag"]
    mean_labels = [f"{pre}IMEAN_WAVE{i}" for i in [1, 2] for pre in ["", "SIG"]]
    anom_labels = [
        f"{pre}I_WAVE{i}({sgn})"
        for i in [1, 2]
        for pre in ["", "SIG"]
        for sgn in ["+", "-"]
    ]
    amp_labels = [f"{pre}F_WAVE{i}" for i in [1, 2] for pre in ["", "SIG"]]
    anom_amp_labels = [
        f"{pre}F_WAVE{i}({sgn})"
        for i in [1, 2]
        for pre in ["", "SIG"]
        for sgn in ["+", "-"]
    ]

    location = dials_data("l_cysteine_4_sweeps_scaled", pathlib=True)
    refl1 = location / "scaled_30.refl"
    expt1 = location / "scaled_30.expt"
    refl2 = location / "scaled_35.refl"
    expt2 = location / "scaled_35.expt"
    expts1 = load.experiment_list(expt1, check_format=False)
    expts1[0].beam.set_wavelength(0.7)
    expts2 = load.experiment_list(expt2, check_format=False)
    expts1.extend(expts2)

    tmp_expt = tmp_path / "tmp.expt"
    expts1.as_json(tmp_expt)

    reflections1 = flex.reflection_table.from_file(refl1)
    reflections2 = flex.reflection_table.from_file(refl2)
    # first need to resolve identifiers - usually done on loading
    reflections2["id"] = flex.int(reflections2.size(), 1)
    del reflections2.experiment_identifiers()[0]
    reflections2.experiment_identifiers()[1] = "3"
    reflections1.extend(reflections2)

    tmp_refl = tmp_path / "tmp.refl"
    reflections1.as_file(tmp_refl)

    # Can now run after creating our 'fake' multiwavelength dataset
    command = [
        shutil.which("dials.merge"),
        tmp_refl,
        tmp_expt,
        "truncate=True",
        "anomalous=True",
    ]
    result = subprocess.run(command, cwd=tmp_path, capture_output=True)
    assert not result.returncode and not result.stderr
    assert (tmp_path / "merged.mtz").is_file()
    assert (tmp_path / "dials.merge.html").is_file()
    m = mtz.object(str(tmp_path / "merged.mtz"))
    labels = []
    for ma in m.as_miller_arrays(merge_equivalents=False):
        labels.extend(ma.info().labels)
    assert all(x in labels for x in r_free_labels)
    assert all(x in labels for x in mean_labels)
    assert all(x in labels for x in anom_labels)
    assert all(x in labels for x in amp_labels)
    assert all(x in labels for x in anom_amp_labels)

    # 7 miller arrays for each dataset, plus FreeR_flag, check the expected number of reflections.
    arrays = m.as_miller_arrays()
    assert len(arrays) == 15
    assert arrays[1].info().wavelength == pytest.approx(0.7)
    assert arrays[8].info().wavelength == pytest.approx(0.6889)
    assert abs(arrays[1].size() - 1223) < 10  # check number of miller indices
    assert abs(arrays[8].size() - 1453) < 10  # check number of miller indices

    # test changing the wavelength tolerance such that data is combined under
    # one wavelength. Check the number of reflections to confirm this.
    command = [
        shutil.which("dials.merge"),
        tmp_refl,
        tmp_expt,
        "truncate=True",
        "anomalous=True",
        "wavelength_tolerance=0.02",
    ]
    result = subprocess.run(command, cwd=tmp_path, capture_output=True)
    assert not result.returncode and not result.stderr
    m = mtz.object(str(tmp_path / "merged.mtz"))
    arrays = m.as_miller_arrays()
    assert arrays[1].info().wavelength == pytest.approx(0.69441, abs=1e-5)
    assert len(arrays) == 8
    assert abs(arrays[1].size() - 1538) < 10

def test_suitable_exit_for_bad_input_from_single_dataset(dials_data, tmp_path):
    location = dials_data("vmxi_proteinase_k_sweeps", pathlib=True)

    command = [
        shutil.which("dials.merge"),
        location / "experiments_0.json",
        location / "reflections_0.pickle",
    ]

    # unscaled data
    result = subprocess.run(command, cwd=tmp_path, capture_output=True)
    assert result.returncode
    assert (
        result.stderr.replace(b"\r", b"")
        == b"""Sorry: intensity.scale.value not found in the reflection table.
Only scaled data can be processed with dials.merge
"""
    )

def test_suitable_exit_for_bad_input_with_more_than_one_reflection_table(
    dials_data, tmp_path
):
    location = dials_data("vmxi_proteinase_k_sweeps", pathlib=True)

    command = [
        shutil.which("dials.merge"),
        location / "experiments_0.json",
        location / "reflections_0.pickle",
        location / "experiments_1.json",
        location / "reflections_1.pickle",
    ]

    # more than one reflection table.
    result = subprocess.run(command, cwd=tmp_path, capture_output=True)
    assert result.returncode
    assert (
        result.stderr.replace(b"\r", b"")
        == b"""Sorry: Only data scaled together as a single reflection dataset
can be processed with dials.merge
"""
    )

def test_merge_exclude_images(dials_data, tmp_path):
    """Test the command line script with LCY data: exclude_images"""

    location = dials_data("l_cysteine_4_sweeps_scaled", pathlib=True)
    refls = location / "scaled_30.refl"
    expts = location / "scaled_30.expt"

    mtz_file = tmp_path / "merge-exclude.mtz"

    command = [
        shutil.which("dials.merge"),
        refls,
        expts,
        f"output.mtz={str(mtz_file)}",
        "exclude_images=0:851:1700",
        "d_min=0.59",
    ]
    result = subprocess.run(command, cwd=tmp_path, capture_output=True)
    assert not result.returncode and not result.stderr

    # all the data together is 75% complete

    for record in result.stdout.decode().split("\n"):
        if record.startswith("Completeness"):
            assert float(record.split()[1]) < 70


import setuptools

with open("README.md", "r", encoding="utf-8") as fh:
    long_description = fh.read()

setuptools.setup(
    name="darcyai",
    author="darcy.ai",
    author_email="info@darcy.ai",
    description="DarcyAI Library",
    keywords="darcy, darcyai",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/darcyai/darcyai",
    project_urls={
        "Documentation": "https://darcyai.github.io/darcyai/",
        "Bug Reports":
        "https://github.com/darcyai/darcyai/issues",
        "Source Code": "https://github.com/darcyai/darcyai"
    },
    include_package_data=True,
    package_data={
        "darcyai": [
            "src/darcyai/swagger/*",
            "src/darcyai/perceptor/coral/models/*",
            "src/darcyai/perceptor/cpu/models/*",
            "src/darcyai/perceptor/posenet_lib/*",
            "src/darcyai/input/bars.png",
        ]
    },
    exclude_package_data={
        "darcyai": [
            "src/examples/*"
        ]
    },
    package_dir={"": "src"},
    packages=setuptools.find_packages(where="src"),
    classifiers=[
        "Development Status :: 2 - Pre-Alpha",
        "Intended Audience :: Developers"
    ],
    python_requires=">=3.6.9",
    install_requires=[
        "pillow==9.0.1",
        "imutils==0.5.4",
        "pytest==6.2.5",
        "flask==2.0.2",
        "requests==2.26.0",
        "logging-json==0.2.1",
        "waitress==2.1.2",
    ]
)


import os
import subprocess
import pytest

from psyclone.tests.lfric_build import LFRicBuild
from psyclone.tests.utilities import Compile, CompileError

@pytest.fixture(name="enable_compilation")
def protect_infrastructure_path_fixture(monkeypatch):
    '''A pytest fixture that mocks testing with compilation enabled while
    ensuring that any pre-existing LFRicBuild._compilation_path is
    preserved.'''
    # Pretend that the infrastructure has already been built so that the
    # LFRicBuild constructor doesn't attempt to trigger it.
    monkeypatch.setattr(LFRicBuild, "_infrastructure_built", True)
    # Pretend that compilation testing is enabled.
    monkeypatch.setattr(Compile, "TEST_COMPILE", True)
    # If compilation testing is enabled then the infrastructure lib will
    # already have been built so we use monkeypatch to ensure its
    # location is automatically restored at the end of this test.
    monkeypatch.setattr(LFRicBuild, "_compilation_path", "/no/path")

def test_lf_build_get_infrastructure_flags(monkeypatch, tmpdir):
    '''
    Test the get_infrastructure_flags method.

    '''
    # Pretend that compilation testing is disabled.
    monkeypatch.setattr(Compile, "TEST_COMPILE", False)
    builder = LFRicBuild(tmpdir)
    flags = builder.get_infrastructure_flags()
    dir_list = []
    for idx, flag in enumerate(flags):
        if idx % 2 == 0:
            assert flag == '-I'
        else:
            # Just keep a list of the base directories
            dir_list.append(os.path.split(flag)[1])
    assert 'configuration' in dir_list
    assert 'function_space' in dir_list
    assert 'field' in dir_list

@pytest.mark.usefixtures("enable_compilation")
def test_lfric_build_compiler_flags(tmpdir, monkeypatch):
    '''
    Check that the compiler settings supplied to pytest are passed through
    when building the (stub) LFRic infrastructure.

    '''
    def fake_popen(arg_list, stdout=None, stderr=None):
        '''Mock implementation of Popen that just raises an Exception.'''
        raise OSError(f"arg_list = {arg_list}")

    # Monkeypatch subprocess.Popen so that it just raises an exception.
    monkeypatch.setattr(subprocess, "Popen", fake_popen)
    builder = LFRicBuild(tmpdir)
    # Set-up a custom compiler and flags.
    builder._f90 = "my_compiler"
    builder._f90flags = "-my -special -flags"
    # Finally, check that these get passed through to the call to Popen when
    # the infrastructure is built.
    with pytest.raises(CompileError) as err:
        builder._build_infrastructure()
    assert ("['make', 'F90=my_compiler', 'F90FLAGS=-my -special -flags', '-f'"
            in str(err.value))

@pytest.mark.usefixtures("enable_compilation")
def test_lfric_build_infrastructure(tmpdir, monkeypatch):
    '''
    Test the _build_infrastructure method when compilation appears to proceed
    (i.e. the Popen.subprocess() command completes without raising an
    exception). Test with a return status of both 0 (success) and 1 (fail).

    '''
    class Build():
        '''Mock object for use when monkeypatching Popen.'''
        RETURN_CODE = 1

        def __init__(self):
            self.returncode = Build.RETURN_CODE

        def __enter__(self):
            return self

        def __exit__(self, _1, _2, _3):
            return

        def communicate(self):
            '''
            :returns: fake stdout output.
            :rtype: Tuple[bytes, NoneType]
            '''
            return (bytes("fake_out", "utf-8"), None)

    def fake_popen(arg_list, stdout=None, stderr=None):
        '''Mock implementation of Popen that just returns a Build instance.'''
        # pylint: disable=unused-argument
        return Build()

    # Monkeypatch subprocess.Popen so that compilation appears to run but
    # returns a status of 1.
    monkeypatch.setattr(subprocess, "Popen", fake_popen)
    builder = LFRicBuild(tmpdir)
    with pytest.raises(CompileError) as err:
        builder._build_infrastructure()
    assert "Compile error: fake_out" in str(err.value)
    # Repeat but alter the Build class to mock a successful build (return
    # status of 0).
    monkeypatch.setattr(Build, "RETURN_CODE", 0)
    monkeypatch.setattr(LFRicBuild, "_infrastructure_built", False)
    builder._build_infrastructure()
    # Check that the '_infrastructure_built' flag is set after a successful
    # build.
    assert LFRicBuild._infrastructure_built is True


"""Lauches the acorn ui server and opens the browser to the correct page.
"""
import webbrowser
import os
from multiprocessing import Process
import time

def open_window():
    """Opens a new tab for the acorn notebook to be displayed in.
    """
    time.sleep(1)
    webbrowser.open('http://127.0.0.1:8000/',new=2,autoraise=True)

def launch_server():
    """Launches the django server at 127.0.0.1:8000
    """
    print(os.path.dirname(os.path.abspath(__file__)))
    cur_dir = os.getcwd()
    path = os.path.dirname(os.path.abspath(__file__))
    run = True
    os.chdir(path)
    os.system('python manage.py runserver --nostatic')
    os.chdir(cur_dir)

if __name__ == '__main__':
    Process(target=launch_server).start()
    Process(target=open_window).start()


import logging
import sys,os
import pandas as pd
from income.exception import CustomException
from income.utils import load_object
from income.predictor import ModelResolver
import sklearn

PREDICTION_DIR = "prediction"

class PredictPipeline:
    def __init__(self):
        pass

    def predict(self, features):
        try:
            os.makedirs(PREDICTION_DIR, exist_ok=True)
            logging.info(f"Creating model resolver object")
            model_resolver = ModelResolver(model_registry="saved_models")
            logging.info(f"Reading file :{features}")

            logging.info(f"Loading transformer to transform dataset")
            transformer = load_object(file_path=model_resolver.get_latest_transformer_path())
            model = load_object(file_path=model_resolver.get_latest_model_path())

            input_arr = transformer.transform(features)

            prediction = model.predict(input_arr)

            return prediction

        except Exception as e:
            raise CustomException(e, sys)

class CustomData:
    def __init__(self,
                 age: float,
                 workclass: str,
                 education_num:int,
                 marital_status: str,
                 occupation: str,
                 relationship: str,
                 race: str,
                 sex:str,
                 capital_gain:int,
                 capital_loss:int,
                 hours_per_week:int,
                 country:str):

        self.age = age

        self.workclass = workclass

        self.education_num = education_num

        self.marital_status = marital_status

        self.occupation = occupation

        self.relationship = relationship

        self.race = race

        self.sex = sex

        self.capital_gain = capital_gain

        self.capital_loss = capital_loss

        self.hours_per_week = hours_per_week

        self.country = country

    def get_data_as_data_frame(self):
        try:
            custom_data_input_dict = {
                "age": [self.age],
                "workclass": [self.workclass],
                "education-num": [self.education_num],
                "marital-status": [self.marital_status],
                "occupation": [self.occupation],
                "relationship": [self.relationship],
                "race": [self.race],
                "sex": [self.sex],
                "capital-gain": [self.capital_gain],
                "capital-loss": [self.capital_loss],
                "hours-per-week": [self.hours_per_week],
                "country": [self.country],

            }

            df = pd.DataFrame(custom_data_input_dict)
            # Remove leading and trailing spaces from all columns
            df = df.applymap(lambda x: x.strip() if isinstance(x, str) else x)
            return df

        except Exception as e:
            raise CustomException(e, sys)


import numpy as np
import json
import pandas as pd

def create_json(path, save_json_path):

    bad_files = [
    "test_132.jpg",
    "test_1346.jpg",
    "test_184.jpg",
    "test_1929.jpg",
    "test_2028.jpg",
    "test_22.jpg",
    "test_232.jpg",
    "test_2321.jpg",
    "test_2613.jpg",
    "test_2643.jpg",
    "test_274.jpg",
    "test_2878.jpg",
    "test_521.jpg",
    "test_853.jpg",
    "test_910.jpg",
    "test_923.jpg",
    "train_1239.jpg",
    "train_2376.jpg",
    "train_2903.jpg",
    "train_2986.jpg",
    "train_305.jpg",
    "train_3240.jpg",
    "train_340.jpg",
    "train_3556.jpg",
    "train_3560.jpg",
    "train_38.jpg",
    "train_3832.jpg",
    "train_4222.jpg",
    "train_5007.jpg",
    "train_5137.jpg",
    "train_5143.jpg",
    "train_5762.jpg",
    "train_5822.jpg",
    "train_6052.jpg",
    "train_6090.jpg",
    "train_6138.jpg",
    "train_6409.jpg",
    "train_6722.jpg",
    "train_6788.jpg",
    "train_737.jpg",
    "train_7576.jpg",
    "train_7622.jpg",
    "train_775.jpg",
    "train_7883.jpg",
    "train_789.jpg",
    "train_8020.jpg",
    "train_8146.jpg",
    "train_882.jpg",
    "train_903.jpg",
    "train_924.jpg",
    "val_147.jpg",
    "val_286.jpg",
    "val_296.jpg",
    "val_386.jpg"
    ]

    data = pd.read_csv(path, usecols=[0,1,2,3,4,5,6,7], names=['filename','xmin','ymin','xmax','ymax','class','width','height'], header=None)

    for n in bad_files:
        data = data.drop(data[data['filename'] == n].index)

    images = []
    categories = []
    annotations = []

    category = {}
    category["supercategory"] = 'none'
    category["id"] = 1
    category["name"] = 'None'
    categories.append(category)

    data['fileid'] = data['filename'].astype('category').cat.codes
    data['categoryid']= pd.Categorical(data['class'],ordered= True).codes
    data['categoryid'] = data['categoryid']+1
    data['annid'] = data.index

    def image(row):
        image = {}
        image["height"] = row.height
        image["width"] = row.width
        image["id"] = row.fileid
        image["file_name"] = row.filename
        return image

    def category(row):
        category = {}
        category["supercategory"] = 'None'
        category["id"] = row.categoryid
        category["name"] = row[2]
        return category

    def annotation(row):
        annotation = {}
        area = 100
        #area = (row.xmax -row.xmin)*(row.ymax - row.ymin)
        annotation["segmentation"] = []
        annotation["iscrowd"] = 0
        annotation["area"] = area
        annotation["image_id"] = row.fileid

        annotation["bbox"] = [row.xmin, row.ymin, row.xmax -row.xmin,row.ymax-row.ymin ]

        annotation["category_id"] = row.categoryid
        annotation["id"] = row.annid
        return annotation

    for row in data.itertuples():
        annotations.append(annotation(row))

    imagedf = data.drop_duplicates(subset=['fileid']).sort_values(by='fileid')
    for row in imagedf.itertuples():
        images.append(image(row))

    catdf = data.drop_duplicates(subset=['categoryid']).sort_values(by='categoryid')
    for row in catdf.itertuples():
        categories.append(category(row))

    data_coco = {}
    data_coco["images"] = images
    data_coco["categories"] = categories
    data_coco["annotations"] = annotations
    json.dump(data_coco, open(save_json_path, "w"), indent=4)


import subprocess
from pathlib import Path

import pytest
from click.testing import CliRunner

from simplec import cli

def fixture_path(path):
    return str(Path(__file__).parent / path)

@pytest.mark.parametrize(
    "src,returncode",
    [
        ("fixtures/one.c", 1),
        ("fixtures/add.c", 8),
        ("fixtures/call.c", 45),
    ],
)
def test_compiler(tmpdir, src, returncode):
    runner = CliRunner()
    result = runner.invoke(cli.compiler, [fixture_path(src)])
    assert result.exit_code == 0

    asm_path = tmpdir / f"{Path(src).stem}.s"
    exe_path = tmpdir / Path(src).stem
    with open(asm_path, "w") as fp:
        fp.write(result.output)

    assert (
        subprocess.run(
            ["arm-linux-gnueabihf-gcc", str(asm_path), "-o", str(exe_path)]
        ).returncode
        == 0
    )
    result = subprocess.run(
        ["qemu-arm-static", "-L", "/usr/arm-linux-gnueabihf/", str(exe_path)],
        capture_output=True,
    )
    assert result.returncode == returncode


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

# Test spherical earth model functions and methods.

__all__ = ('Tests',)
__version__ = '17.08.10'

from testLatLon import Tests as _TestsLL
from testVectorial import Tests as _TestsV

from pygeodesy import F_D, F_DMS, lonDMS

class Tests(_TestsLL, _TestsV):

    def testSpherical(self, module):

        self.subtitle(module, 'Spherical')

        LatLon = module.LatLon

        p = LatLon(51.8853, 0.2545)
        self.test('isSpherical', p.isSpherical, True)
        self.test('isEllipsoidal', p.isEllipsoidal, False)

        q = LatLon(49.0034, 2.5735)
        self.test('isSpherical', q.isSpherical, True)
        self.test('isEllipsoidal', q.isEllipsoidal, False)

        i = p.intersection(108.55, q, 32.44)
        self.test('intersection', i.toStr(F_D),  '50.907608°N, 004.508575°E')  # 50.9076°N, 004.5086°E  # Trig
        self.test('intersection', i.toStr(F_DMS), '50°54′27.39″N, 004°30′30.87″E')
        self.test('intersection', isinstance(i, LatLon), True)

        REO = LatLon(42.600, -117.866)
        BKE = LatLon(44.840, -117.806)
        i = REO.intersection(51, BKE, 137)
        self.test('intersection', i.toStr(F_D), '43.5719°N, 116.188757°W')  # 43.572°N, 116.189°W
        self.test('intersection', i.toStr(F_DMS), '43°34′18.84″N, 116°11′19.53″W')
        self.test('intersection', isinstance(i, LatLon), True)

        p = LatLon(0, 0)
        self.test('maxLat0',  p.maxLat( 0), '90.0')
        self.test('maxLat1',  p.maxLat( 1), '89.0')
        self.test('maxLat90', p.maxLat(90),  '0.0')

        if hasattr(LatLon, 'crossingParallels'):
            ps = p.crossingParallels(LatLon(60, 30), 30)
            t = ', '.join(map(lonDMS, ps))
            self.test('crossingParallels', t, '009°35′38.65″E, 170°24′21.35″E')

        if hasattr(LatLon, 'isEnclosedBy'):
            p = LatLon(45.1, 1.1)

            b = LatLon(45, 1), LatLon(45, 2), LatLon(46, 2), LatLon(46, 1)
            for _ in self.testiter():
                self.test('isEnclosedBy', p.isEnclosedBy(b), True)

            b = LatLon(45, 1), LatLon(45, 3), LatLon(46, 2), LatLon(47, 3), LatLon(47, 1)
            for _ in self.testiter():
                try:
                    self.test('isEnclosedBy', p.isEnclosedBy(b), True)  # Nvector
                except ValueError as x:
                    t = ' '.join(str(x).split()[:3] + ['...)'])
                    self.test('isEnclosedBy', t, 'non-convex: (LatLon(45°00′00.0″N, 001°00′00.0″E), ...)')  # Trig

        p = LatLon(51.127, 1.338)
        q = LatLon(50.964, 1.853)
        b = p.rhumbBearingTo(q)
        self.test('rhumbBearingTo', b, 116.722, fmt='%.3f')  # 116.7

        d = p.rhumbDestination(40300, 116.7)
        self.test('rhumbDestination', d, '50.964155°N, 001.853°E')  # 50.9642°N, 001.8530°E
        self.test('rhumbDestination', isinstance(d, LatLon), True)

        d = p.rhumbDistanceTo(q)
        self.test('rhumbDistanceTo', d, 40307.8, fmt='%.1f')  # XXX 40310 ?

        m = p.rhumbMidpointTo(q)
        self.test('rhumbMidpointo', m, '51.0455°N, 001.595727°E')
        self.test('rhumbMidpointo', isinstance(m, LatLon), True)

        b = LatLon(45, 1), LatLon(45, 2), LatLon(46, 2), LatLon(46, 1)
        self.test('areaOf', module.areaOf(b), '8.6660587507e+09', fmt='%.10e')  # 8666058750.718977

        c = LatLon(0, 0), LatLon(1, 0), LatLon(0, 1)
        self.test('areaOf', module.areaOf(c), '6.18e+09', fmt='%.2e')

        if hasattr(module, 'isPoleEnclosedBy'):
            b = LatLon(85, 90), LatLon(85, 0), LatLon(85, -90), LatLon(85, -180)
            for _ in self.testiter():
                self.test('isPoleEnclosedBy', module.isPoleEnclosedBy(b), 'True')
            b = LatLon(85, 90), LatLon(85, 0), LatLon(85, -180)
            for _ in self.testiter():
                self.test('isPoleEnclosedBy', module.isPoleEnclosedBy(b), 'True', known=True)

if __name__ == '__main__':

    from pygeodesy import sphericalNvector as N, \
                          sphericalTrigonometry as T

    t = Tests(__file__, __version__)

    t.testLatLon(N, Sph=True)
    t.testSpherical(N)
    t.testVectorial(N)

    t.testLatLon(T, Sph=True)
    t.testSpherical(T)

    t.results()
    t.exit()


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

# In[1]:

import json

# In[30]:

# modelPath = '../output/testBigramModel.json'
modelPath = '../output/bigramModel.json'
UomodelPath = '../output/UObigramModel.json'
limit = 6
#https://stackoverflow.com/questions/35624064/sorting-dictionary-descending-in-python

# In[35]:

def findNext(query,collection):
    # Let's assume the query is of form "abc cde "
    mPath = modelPath
    if collection == "UofO catalog":
        mPath = UomodelPath
    with open(mPath,'r') as f:
        file = json.load(f)
        previousWord = query.split()[-1]
        d = file[previousWord]
        sortedProb = {k: v for k, v in sorted(d.items(), key=lambda item: item[1],reverse=True)}
        return [query + x for x in list(sortedProb)[0:limit]]

# In[19]:

#list(newf)[0:3]

# In[37]:

# print(findNext("U.S. would ")
# print(findNext("boo ")


import sqlite3

con = sqlite3.connect(r"e:\classroom\python\hr.db")
cur = con.cursor()

cur.execute("select * from jobs order by minsal desc")
jobs = cur.fetchall()
for id, title, minsal in jobs:
    print(f"{id:3d} {title:30s} {minsal:6d}")

con.close()


import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
ax = Axes3D(fig)

x = np.arange(0, 200)
y = np.arange(0, 100)
x, y = np.meshgrid(x, y)
z = np.random.randint(0, 200, size=(100, 200))%3
print(z.shape)

# ax.scatter(x, y, z, c='r', marker='.', s=50, label='')
ax.plot_surface(x, y, z,label='')
plt.show()


#! /usr/bin/env python3
# -*- coding: utf-8 -*-

__author__ = "Cchen Zhang"

import time, threading, multiprocessing

balance = 0
lock = threading.Lock()
threadpool = []

def loop():
    print('thread %s is running' % threading.current_thread().name)
    n = 0
    while n < 5:
        n = n + 1
        print('thread %s >>> %s' % (threading.current_thread().name, n))
        time.sleep(1)
    print('thread %s end' % threading.current_thread().name)

def dead_loop():
    n = 0
    while True:
        n = n ^ 1

def change_value(n):
    global balance
    balance = balance + n
    balance = balance - n

def run_thread(n):
    for i in range(1000):
        lock.acquire()
        try:
            change_value(n)
        finally:
            lock.release()

def test_multiThread():
    print('thread %s is running' % threading.current_thread().name)
    t1 = threading.Thread(target=run_thread, name='t1', args=(5,))
    t2 = threading.Thread(target=run_thread, name='t2', args=(-8,))
    t1.start()
    t2.start()
    t1.join()
    t2.join()
    print(balance)
    print('thread %s is end' % threading.current_thread().name)

def test_thread_cpu():
    n = multiprocessing.cpu_count()
    print(n)
    for i in range(n):
        t = threading.Thread(target=dead_loop())
        print('start new thread')
        threadpool.append(t)
        t.start()

def main():
    # test_multiThread()
    test_thread_cpu()
    time.sleep(10)
    for t in threadpool:
        t.terminate()

if __name__ == '__main__':
    main()


import mido
import sys
import time
import json

midi_name = None
for name in mido.get_output_names():
  if name.startswith("VYPYR"):
    midi_name = name

if not midi_name:
  print("Could not find VYPYR interface")
  sys.exit(1)

output = mido.open_output(midi_name)

while True:
  line = sys.stdin.readline()
  data = json.loads(line)
  msg = mido.Message(**data) # "program_change", program=int(sys.argv[1]))
  output.send(msg)


import pickle
import pandas as pd
import numpy as np
from functools import cached_property
from dfs_tools_mlb import settings
from dfs_tools_mlb import config
from dfs_tools_mlb.utils.storage import pickle_path
from dfs_tools_mlb.utils.time import time_frames as tf
from dfs_tools_mlb.compile import teams
from dfs_tools_mlb.utils.pd import modify_team_name
from dfs_tools_mlb.utils.pd import sm_merge_single
import random

class FDSlateSingle:
    def __init__(
        self,
        entries_file=config.get_fd_file(),
        slate_number=1,
        lineups=150,
        stack_points_weight=2,
        stack_threshold=120,
        heavy_weight_stack=False,
        max_batting_order=7,
        h_fades=[],
    ):

        self.entry_csv = entries_file
        if not self.entry_csv:
            raise TypeError(
                "There are no fanduel entries files in specified DL_FOLDER, obtain one at fanduel.com/upcoming"
            )

        self.slate_number = slate_number
        self.lineups = lineups

        self.points_weight = stack_points_weight
        self.stack_threshold = stack_threshold

        self.heavy_weight_stack = heavy_weight_stack

        self.max_batting_order = max_batting_order
        self.h_fades = h_fades

    def entries_df(self, reset=False):
        df_file = pickle_path(
            name=f"lineup_entries_{tf.today}_{self.slate_number}",
            directory=settings.FD_DIR,
        )
        path = settings.FD_DIR.joinpath(df_file)
        if path.exists() and not reset:
            df = pd.read_pickle(path)
        else:
            cols = [
                "entry_id",
                "contest_id",
                "contest_name",
                "MVP - 2X Points",
                "STAR - 1.5X Points",
                "UTIL",
                "UTIL.1",
                "UTIL.2",
            ]
            csv_file = self.entry_csv
            with open(csv_file, "r") as f:
                df = pd.read_csv(f, usecols=cols)
            df = df[~df["entry_id"].isna()]
            df = df.astype({"entry_id": np.int64})
            with open(df_file, "wb") as f:
                pickle.dump(df, f)
        return df

    @cached_property
    def player_info_df(self):
        df_file = pickle_path(
            name=f"player_info_{tf.today}_{self.slate_number}",
            directory=settings.FD_DIR,
        )
        path = settings.FD_DIR.joinpath(df_file)
        if path.exists():
            df = pd.read_pickle(path)
        else:
            cols = [
                "Player ID + Player Name",
                "Id",
                "Position",
                "First Name",
                "Nickname",
                "Last Name",
                "FPPG",
                "Salary",
                "Game",
                "Team",
                "Opponent",
                "Injury Indicator",
                "Injury Details",
                "Roster Position",
            ]
            csv_file = self.entry_csv
            with open(csv_file, "r") as f:
                df = pd.read_csv(f, skiprows=lambda x: x < 6, usecols=cols)
            df.rename(
                columns={
                    "Id": "fd_id",
                    "Player ID + Player Name": "fd_id_name",
                    "Nickname": "name",
                    "Position": "fd_position",
                    "Roster Position": "fd_r_position",
                    "Injury Indicator": "fd_injury_i",
                    "Injury Details": "fd_injury_d",
                    "Opponent": "opp",
                    "First Name": "f_name",
                    "Last Name": "l_name",
                    "Salary": "fd_salary",
                },
                inplace=True,
            )

            df.columns = df.columns.str.lower()
            df = modify_team_name(df, columns=["team", "opp"])

            with open(df_file, "wb") as f:
                pickle.dump(df, f)
        return df

    @cached_property
    def active_teams(self):
        return self.player_info_df["team"].unique()

    @cached_property
    def default_stack_dict(self):
        team_dict = {}
        for team in self.active_teams:
            team_dict[team] = 0
        return team_dict

    def insert_lineup(self, idx, lineup):
        cols = ["MVP - 2X Points", "STAR - 1.5X Points", "UTIL", "UTIL.1", "UTIL.2"]
        df = self.entries_df()
        df.loc[idx, cols] = lineup
        file = pickle_path(
            name=f"lineup_entries_{tf.today}_{self.slate_number}",
            directory=settings.FD_DIR,
        )
        with open(file, "wb") as f:
            pickle.dump(df, f)
        return f"Inserted {lineup} at index {idx}."

    def finalize_entries(self):
        df = self.entries_df()
        csv = self.entry_csv
        df.rename(columns={"UTIL.1": "UTIL", "UTIL.2": "UTIL"}, inplace=True)
        df.to_csv(csv, index=False)
        return f"Stored lineups at {csv}"

    @cached_property
    def team_instances(self):
        instances = set()
        for team in teams.Team:
            if team.name in self.active_teams:
                instances.add(team)
        return instances

    def get_hitters(self):
        df_file = pickle_path(
            name=f"all_h_{tf.today}_{self.slate_number}", directory=settings.FD_DIR
        )
        path = settings.FD_DIR.joinpath(df_file)
        for team in self.team_instances:
            hitters = team.lineup_df()
            merge = self.player_info_df[(self.player_info_df["team"] == team.name)]
            hitters = sm_merge_single(hitters, merge, ratio=0.75, suffixes=("", "_fd"))
            hitters.drop_duplicates(subset="mlb_id", inplace=True)
            order_filter = hitters["order"] <= self.max_batting_order
            hitters_order = hitters[order_filter]
            team.salary = hitters_order["fd_salary"].sum() / len(hitters_order.index)
            cols = [
                "raw_points",
                "venue_points",
                "temp_points",
                "points",
                "salary",
                "sp_mu",
            ]
            points_file = pickle_path(
                name=f"team_points_{tf.today}_{self.slate_number}",
                directory=settings.FD_DIR,
            )
            points_path = settings.FD_DIR.joinpath(points_file)
            if points_path.exists():
                p_df = pd.read_pickle(points_path)
            else:
                p_df = pd.DataFrame(columns=cols)
            p_df.loc[team.name, cols] = [
                team.raw_points,
                team.venue_points,
                team.temp_points,
                team.points,
                team.salary,
                team.sp_mu,
            ]
            with open(points_file, "wb") as f:
                pickle.dump(p_df, f)
            if path.exists():
                df = pd.read_pickle(path)
                df.drop(index=df[df["team"] == team.name].index, inplace=True)
                df = pd.concat([df, hitters], ignore_index=True)
            else:
                df = hitters
            with open(df_file, "wb") as f:
                pickle.dump(df, f)

        return df

    def h_df(self):
        df_file = pickle_path(
            name=f"all_h_{tf.today}_{self.slate_number}", directory=settings.FD_DIR
        )
        path = settings.FD_DIR.joinpath(df_file)
        if not path.exists():
            df = self.get_hitters()
        else:
            df = pd.read_pickle(path)
        return df

    def points_df(self):
        file = pickle_path(
            name=f"team_points_{tf.today}_{self.slate_number}",
            directory=settings.FD_DIR,
        )
        path = settings.FD_DIR.joinpath(file)
        if not path.exists():
            self.get_hitters()
        df = pd.read_pickle(path).apply(pd.to_numeric)
        return df

    def stacks_df(self):
        lineups = self.lineups
        df = self.points_df()

        df["p_z"] = (
            (df["points"] - df["points"].mean()) / df["points"].std()
        ) * self.points_weight
        df["s_z"] = ((df["salary"] - df["salary"].mean()) / df["salary"].std()) * -(
            2 - self.points_weight
        )
        df["stacks"] = 1000
        increment = 0
        while df["stacks"].max() > self.stack_threshold:
            df_c = df.copy()
            df_c["z"] = ((df_c["p_z"] + df_c["s_z"]) / 2) + increment
            df_c = df_c[df_c["z"] > 0]
            lu_base = lineups / len(df_c.index)
            df_c["stacks"] = lu_base * df_c["z"]
            if df_c["stacks"].max() > self.stack_threshold:
                increment += 0.01
                continue
            diff = lineups - df_c["stacks"].sum()
            df_c["stacks"] = round(df_c["stacks"])
            while df_c["stacks"].sum() < lineups:
                if self.heavy_weight_stack:
                    df_c["stacks"] = df_c["stacks"] + np.ceil(
                        ((diff / len(df.index)) * df_c["z"])
                    )
                else:
                    df_c["stacks"] = df_c["stacks"] + np.ceil((diff / len(df.index)))
                df_c["stacks"] = round(df_c["stacks"])
            while df_c["stacks"].sum() > lineups:
                for idx in df_c.index:
                    if df_c["stacks"].sum() == lineups:
                        break
                    else:
                        df_c.loc[idx, "stacks"] -= 1
            if df_c["stacks"].max() > self.stack_threshold:
                increment += 0.01
                continue
            df = df_c

        i = df[df["stacks"] == 0].index
        df.drop(index=i, inplace=True)
        return df

    def h_counts(self):
        file = pickle_path(
            name=f"h_counts_{tf.today}_{self.slate_number}", directory=settings.FD_DIR
        )
        path = settings.FD_DIR.joinpath(file)
        if path.exists():
            df = pd.read_pickle(path)
            return df
        else:
            return "No lineups stored yet."

    def build_lineups(
        self,
        lus=150,
        index_track=0,
        max_lu_total=90,
        max_sal=35000,
        stack_sample=4,
        util_replace_filt=1000,
        variance=0,
        non_stack_max_order=5,
        custom_counts={},
        custom_stacks=None,
        below_avg_count=30,
        stack_expand_limit=30,
        exempt=[],
        full_stack_cutoff=50,
    ):
        max_order = self.max_batting_order
        # all hitters in slate
        h = self.h_df()
        # dropping faded, platoon, and low order (max_order) players.
        h_fade_filt = h["fd_id"].isin(self.h_fades)
        h_order_filt = h["order"] > max_order
        h_exempt_filt = ~h["fd_id"].isin(exempt)
        hfi = h[(h_fade_filt | h_order_filt) & h_exempt_filt].index
        h.drop(index=hfi, inplace=True)
        # count each players entries
        h["t_count"] = 0
        # count non_stack
        h["ns_count"] = 0
        h_count_df = h.copy()
        # risk_limit should always be >= below_avg_count
        h.loc[
            (h["exp_ps_sp_pa"] < h["exp_ps_sp_pa"].median()), "t_count"
        ] = below_avg_count
        exempt_filt = h["fd_id"].isin(exempt)
        h.loc[exempt_filt, "t_count"] = 0
        for k, v in custom_counts.items():
            h.loc[h["fd_id"] == k, "t_count"] = v
        # team: stacks to build
        if not custom_stacks:
            s = self.stacks_df()["stacks"].to_dict()
        else:
            s = custom_stacks
        # lineups to build
        sorted_lus = []
        while lus > 0:
            salary = 0
            # if lineup fails requirements, reset will be set to true.
            reset = False
            if lus > full_stack_cutoff:
                stack_size = 4
            else:
                stack_size = 3

            stacks = {k: v for k, v in s.items() if v > 0}
            stack = random.choice(list(stacks.keys()))
            remaining_stacks = stacks[stack]
            # lookup players on the team for the selected stack
            stack_df = h[h["team"] == stack]
            # stack_key = 'exp_ps_sp_pa'
            # non_stack_key = 'exp_ps_sp_pa'
            if remaining_stacks % 4 == 0:
                stack_key = "total_pitches"
            elif remaining_stacks % 3 == 0:
                stack_key = "fd_hr_weight"
            elif remaining_stacks % 2 == 0:
                stack_key = "points"
            else:
                stack_key = "exp_ps_sp_pa"
            if lus % 2 == 0:
                non_stack_key = "exp_ps_sp_pa"
            else:
                non_stack_key = "points"
            # filter the selected stack by stack_sample arg.
            if remaining_stacks > stack_expand_limit:
                highest = stack_df.loc[
                    stack_df[stack_key].nlargest(stack_sample + 1).index
                ]
            else:
                highest = stack_df.loc[stack_df[stack_key].nlargest(stack_sample).index]
            # array of fanduel ids of the selected hitters
            stack_ids = highest["fd_id"].values
            # initial empty lineup, ordered by fanduel structed and mapped by p_map
            lineup = [None, None, None, None, None]
            # insert current pitcher into lineup

            # try to create a 4-man stack that satifies position requirements 5 times, else 3-man stack.
            try:
                samp = random.sample(sorted(stack_ids), stack_size)
            except ValueError:
                samp = random.sample(sorted(stack_ids), stack_size - 1)
            stack_salary = h.loc[h["fd_id"].isin(samp), "fd_salary"].sum()
            salary += stack_salary
            rem_sal = max_sal - salary
            random.shuffle(stack_ids)

            for x, y in enumerate(samp):
                lineup[x] = y

            # filter out hitters on the team of the current stack, as they are already in the lineup.
            stack_filt = h["team"] != stack
            # filter out players hitting below specified lineup spot
            order_filt = (h["order"] <= non_stack_max_order) | exempt_filt
            # filter out players not on a team being stacked on slate and proj. points not in 90th percentile.
            max_stack = max(stacks.values())
            # variance default is 0
            count_filt = h["t_count"] < ((max_lu_total - max_stack) - variance)
            plat_filt = h["is_platoon"] != True
            for y, z in enumerate(lineup):
                if not z:
                    # filter out players already in lineup, lineup will change with each iteration
                    dupe_filt = ~h["fd_id"].isin(lineup)
                    # filter out players not eligible for the current position being filled.
                    # get the ammount of roster spots that need filling.
                    npl = len([idx for idx, spot in enumerate(lineup) if not spot])
                    # the avgerage salary remaining for each empty lineup spot
                    avg_sal = rem_sal / npl
                    # filter out players with a salary greater than the average avg_sal above
                    sal_filt = h["fd_salary"] <= avg_sal

                    try:
                        hitters = h[
                            stack_filt
                            & dupe_filt
                            & count_filt
                            & sal_filt
                            & order_filt
                            & plat_filt
                        ]
                        hitter = hitters.loc[hitters[non_stack_key].idxmax()]
                    except (KeyError, ValueError):
                        try:
                            hitters = h[
                                stack_filt
                                & dupe_filt
                                & count_filt
                                & sal_filt
                                & order_filt
                            ]
                            hitter = hitters.loc[hitters[non_stack_key].idxmax()]
                        except (KeyError, ValueError):
                            try:
                                hitters = h[
                                    stack_filt
                                    & dupe_filt
                                    & count_filt
                                    & sal_filt
                                    & plat_filt
                                ]
                                hitter = hitters.loc[hitters[non_stack_key].idxmax()]
                            except (KeyError, ValueError):
                                try:
                                    hitters = h[
                                        stack_filt
                                        & dupe_filt
                                        & count_filt
                                        & order_filt
                                        & plat_filt
                                    ]
                                    hitter = hitters.loc[
                                        hitters[non_stack_key].idxmax()
                                    ]
                                except:
                                    hitters = h[
                                        stack_filt
                                        & dupe_filt
                                        & sal_filt
                                        & order_filt
                                        & plat_filt
                                    ]
                                    hitter = hitters.loc[
                                        hitters[non_stack_key].idxmax()
                                    ]
                    salary += hitter["fd_salary"].item()
                    rem_sal = max_sal - salary
                    # if the selected hitter's salary put the lineup over the max. salary, try to find replacement.
                    if rem_sal < 0:
                        r_sal = hitter["fd_salary"].item()
                        try:
                            salary_df = hitters[
                                (hitters["fd_salary"] <= (r_sal + rem_sal))
                            ]
                            hitter = salary_df.loc[hitters[non_stack_key].idxmax()]
                            salary += hitter["fd_salary"]
                            salary -= r_sal
                            rem_sal = max_sal - salary
                        except (ValueError, KeyError):
                            try:
                                hitters = h[stack_filt & dupe_filt]
                                salary_df = hitters[
                                    (hitters["fd_salary"] <= (r_sal + rem_sal))
                                ]
                                hitter = salary_df.loc[hitters[non_stack_key].idxmax()]
                                salary += hitter["fd_salary"]
                                salary -= r_sal
                                rem_sal = max_sal - salary

                            except (KeyError, ValueError):
                                reset = True
                                print("resetting")
                                break

                    h_id = hitter["fd_id"]
                    lineup[y] = h_id
                    used_players = []
                    print(lineup)

            while not reset and lineup[0:2] + sorted(lineup[2:5]) in sorted_lus:
                mvp = lineup[0]
                all_star = lineup[1]
                potential_lu = lineup[0:2] + sorted(lineup[2:5])
                potential_lu[0] = all_star
                potential_lu[1] = mvp
                if potential_lu not in sorted_lus:
                    lineup = potential_lu
                    break
                try:
                    # redeclare use_teams each pass
                    h_df = h[h["fd_id"].isin(lineup)]
                    # append players already attempted to used_players and filter them out each loop
                    used_filt = ~h["fd_id"].isin(used_players)
                    dupe_filt = ~h["fd_id"].isin(lineup)
                    utility = h[h["fd_id"] == lineup[4]]
                    used_players.append(utility["fd_id"])
                    r_salary = utility["fd_salary"].item()
                    # only use players with a salary between the (util's salary - util_replace_filt) and maxiumum salary.
                    sal_filt = h["fd_salary"].between(
                        (r_salary - util_replace_filt), (rem_sal + r_salary)
                    )
                    # don't use players on team against current pitcher
                    hitters = h[
                        dupe_filt
                        & sal_filt
                        & used_filt
                        & count_filt
                        & stack_filt
                        & order_filt
                        & plat_filt
                    ]
                    hitter = hitters.loc[hitters[non_stack_key].idxmax()]
                    used_players.append(hitter["fd_id"])
                    salary += hitter["fd_salary"].item()
                    salary -= utility["fd_salary"].item()
                    rem_sal = max_sal - salary
                    lineup[4] = hitter["fd_id"]
                    h_df = h[h["fd_id"].isin(lineup)]
                # same as above, but no fade_filt and increasing minimum thresehold by 100.
                except (KeyError, ValueError):
                    try:
                        # redeclare use_teams each pass
                        h_df = h[h["fd_id"].isin(lineup)]
                        # append players already attempted to used_players and filter them out each loop
                        used_filt = ~h["fd_id"].isin(used_players)
                        dupe_filt = ~h["fd_id"].isin(lineup)
                        utility = h[h["fd_id"] == lineup[3]]
                        used_players.append(utility["fd_id"])
                        r_salary = utility["fd_salary"].item()
                        # only use players with a salary between the (util's salary - util_replace_filt) and maxiumum salary.
                        sal_filt = h["fd_salary"].between(
                            (r_salary - util_replace_filt), (rem_sal + r_salary)
                        )
                        # don't use players on team against current pitcher
                        hitters = h[
                            dupe_filt
                            & sal_filt
                            & used_filt
                            & count_filt
                            & stack_filt
                            & order_filt
                            & plat_filt
                        ]
                        hitter = hitters.loc[hitters[non_stack_key].idxmax()]
                        used_players.append(hitter["fd_id"])
                        salary += hitter["fd_salary"].item()
                        salary -= utility["fd_salary"].item()
                        rem_sal = max_sal - salary
                        lineup[3] = hitter["fd_id"]
                        h_df = h[h["fd_id"].isin(lineup)]
                    except (KeyError, ValueError):
                        reset = True
                        print("resetting")
                        break
            if reset == True:
                continue
            #!!the lineup meets all parameters at this point.!!
            # decrease lus arg, loop ends at 0.
            lus -= 1
            # append the new lineup to the sorted lus list for next loop.
            sorted_lus.append(lineup[0:2] + sorted(lineup[2:5]))
            # insert the lineup in the lineup df
            self.insert_lineup(index_track, lineup)
            # increase index for next lineup insertion.
            index_track += 1
            # decrease the current stack's value, so it won't be attempted once it reaches 0.
            s[stack] -= 1
            # keep track of total insertions and stack insertions, players exceeding max_lu_total will be dropped next loop.
            lu_filt = h["fd_id"].isin(lineup)
            h.loc[lu_filt, "t_count"] += 1
            h.loc[lu_filt & stack_filt, "ns_count"] += 1
            # print(lus)
            # print(index_track)
            print(salary)
            print(lus)
            # keep track of players counts, regardless if they're eventually dropped.
            h_count_df.loc[(h_count_df["fd_id"].isin(lineup)), "t_count"] += 1

        # dump the counts into pickled df for analysis
        h_count_file = pickle_path(
            name=f"h_counts_{tf.today}_{self.slate_number}", directory=settings.FD_DIR
        )

        with open(h_count_file, "wb") as f:
            pickle.dump(h_count_df, f)

        return sorted_lus


"""
Representation of a quiz
"""

import jinja2

default_quiz_template = jinja2.Template("""
{{ quiz_name }} (version: {{ quiz_version }})
{{ preamble }}

{% for question in questions %}
    Question #{{ loop.index }}:
    {{ question.render_question()}}
{% endfor %}
""")

default_marking_sheet_template = jinja2.Template("""
Marking sheet for {{ quiz_name }} version {{ quiz_version }}
{% for question in questions %}
    Answer for question #{{loop.index}}: {{ question.render_answer() }}
{% endfor %}
""")

class Quiz:
    """Represents a particlar instance of a Quiz"""

    def __init__(self, questions, quiz_name="", quiz_version="",
                 preamble=None, quiz_questions_template=default_quiz_template,
                 marking_sheet_template=default_marking_sheet_template):
        """
        :questions: A collection of questions that comprises this quiz
        :quiz_name: The name of this quiz
        :quiz_version: The version of the quiz
        :preamble: Text to appear before quiz any questions
        :quiz_questions_template: A template to display the quiz questions.
                                  See the default for an example.
        :default_marking_sheet_template: A template to display the marking sheet.
                                         See the default for an example.
        """
        self.questions = questions
        self.quiz_name = quiz_name
        self.quiz_version = quiz_version
        self.preamble = preamble
        self.quiz_questions_template = quiz_questions_template
        self.marking_sheet_template = marking_sheet_template

    def add_question(self, question):
        """Add a question to the Quiz"""
        self.questions.append(question)

    def create_marking_sheet(self):
        """Create a marking sheet for this quiz"""
        rendered_output = self.marking_sheet_template.render({
            "quiz_name": self.quiz_name,
            "quiz_version": self.quiz_version,
            "questions": self.questions,
        })
        return rendered_output

    def render(self):
        """
        Render the quiz using the provided template
        :rtype: str
        :returns: A string with the rendered quiz
        """
        rendered_output = self.quiz_questions_template.render({
            "quiz_name": self.quiz_name,
            "quiz_version": self.quiz_version,
            "questions": self.questions,
        })
        return rendered_output


from flask import Flask, request, send_file
import os
import sys
from multiprocessing import Process
import json
from waiting import wait, TimeoutExpired
import time

LIB_ROOT = "/Users/sameal/Documents/PROJECT/zombie_enterprise/code"
sys.path.append(LIB_ROOT)
import predict_tools

app = Flask(__name__)
app.debug = True
app.config["UPLOAD_PATH"] = "/Users/sameal/Documents/PROJECT/zombie_enterprise/web/uploads"

@app.route("/upload", methods=["POST"])
def upload():
    f = request.files["file"]
    key = request.form.get("suffixKey")
    upload_dir = os.path.join(app.config["UPLOAD_PATH"], key)
    if not os.path.exists(upload_dir):
        os.mkdir(upload_dir)
    upload_path = os.path.join(upload_dir, f.filename)
    f.save(upload_path)
    return "Success"

@app.route("/remove", methods=["POST"])
def remove():
    file_name = request.form.get("fileName")
    key = request.form.get("suffixKey")
    file_path = os.path.join(app.config["UPLOAD_PATH"], key, file_name)
    os.remove(file_path)
    pred_path = os.path.join(app.config["UPLOAD_PATH"], key, "result.csv")
    if os.path.exists(pred_path):
        os.remove(pred_path)
    return "Success"

@app.route("/predict", methods=["POST"])
def predict():
    key = request.form.get("suffixKey")
    upload_dir = os.path.join(app.config["UPLOAD_PATH"], key)
    res_path = os.path.join(upload_dir, "result.csv")
    if not os.path.exists(res_path):
        p = Process(target=predict_tools.analyse, args=(upload_dir,))
        p.start()
        predict_tools.predict(upload_dir)
    try:
        return send_file(res_path, mimetype="text/csv", as_attachment=True, attachment_filename="result.csv")
    except Exception as e:
        app.log_exception(e)

@app.route("/search", methods=["GET"])
def search():
    key = request.args.get("suffixKey")
    search_id = request.args.get("id")
    upload_dir = os.path.join(app.config["UPLOAD_PATH"], key)
    portrait_path = os.path.join(upload_dir, "portrait.csv")
    try:
        wait(lambda: os.path.exists(portrait_path), timeout_seconds=10)
        label = predict_tools.search(upload_dir, search_id)
        if label is None:
            return ""
        return label
    except TimeoutExpired:
        return "Timeout", 408

@app.route("/chart", methods=["GET"])
def chart():
    key = request.args.get("suffixKey")
    search_id = request.args.get("id")
    byclass = request.args.get("class")
    upload_dir = os.path.join(app.config["UPLOAD_PATH"], key)
    data = predict_tools.chart(upload_dir, search_id, byclass)
    if data is None:
        return ""
    return data

if __name__ == "__main__":
    app.run(debug=True)