import networkx as nx
import networkx
import src.game.boardTile.tile as tile
import src.game.boardTile.boardGraph as bg

from board import Board
from pathManager import PathManager
import unittest
import pygame
import boardRenderer

class TestPlaceObjs(unittest.TestCase):

    def testGenerateBoard(self):
        width = 5
        height = 5
        board = Board()
        board.generateBoard(width, height)
        self.assertEqual(board.getWidth(), width)
        self.assertEqual(board.getHeight(), height)

    def testGenerateBoardDimensions(self):
        width = 3
        height = 3
        board = Board()
        board.generateBoard(width, height)
        self.assertEqual(board.getWidth(), width)
        self.assertEqual(board.getHeight(), height)
        board.placeObject(2, 2, "First One")
        # board.placeObject(2, 2, "Second One")
        board.debugBoard()

    def testPlaceObjects(self):
        width = 5
        height = 5
        board = Board()
        board.generateBoard(width, height)
        id = 1
        type = "Human"
        x = 3
        y = 4
        player = [id, type, x, y]
        randomStr = "Dis"
        aBigNum = 129023
        board.placeObject(x, y, player)
        board.placeObject(x, y, randomStr)
        board.placeObject(x, y, aBigNum)
        playerReturned = board.getObjsAt(x, y)
        self.assertEqual([player, randomStr, aBigNum], playerReturned)

'''
PathManagerTest:
tests whether there is a move from the current
position
'''
class PathManagerTest(unittest.TestCase):

    def test3x3OnePossibleMoveW(self):

        tileAttr = 'tile'
        width = 3
        height = 3
        board = Board()
        board.generateBoard(width, height)
        player = ["Tester", 42, "180-D"]

        # Place player
        board.placeObject(2,2, player)

        # Place one valid move
        board.placeObject(1, 2, tileAttr)

        pathMgr = PathManager()
        pathMgr.setBoard(board)

        moves = pathMgr.getMovesFromCurPos(2,2, tileAttr)
        self.assertEqual(1, len(moves))
        # works if there is a move from 2,2 to 1,2 and 1,2 is a tile!

'''
BoardGraphTests:
Working with a NetworkX directed graph i created
'''
class BoardGraphTests(unittest.TestCase):

    def testBoardGraphGeneration(self):
        # === Graph Testing ===
        # create the graph for the board
        board = bg.BoardGraph.generateBoard(None)

        print("Number of nodes currently:", board.number_of_nodes())
        print("Number of edges: ", board.number_of_edges())
        print("Paths from 3:", list(iter(board[3])))
        print("Predecessors of 3:", list(board.predecessors(3)))
        # print(board[1].name)
        for tile in board:
            print(tile)

'''
TestWindowDisplay:
Use as a quick reference for displaying and exiting
a window. Can handle fps too
'''
class TestWindowDisplay(unittest.TestCase):
    def testBlankWindow(self):
        print("Hello!")

        # display a window
        pygame.init()
        clock = pygame.time.Clock()  # Clock used for frame rate
        framerate = 60

        isRunning = True
        background = (255, 255, 255)
        mainWindow = pygame.display.set_mode((448, 448))

        pygame.display.update()
        isRunning = True

        # Program is running
        while (isRunning):
            clock.tick(framerate)

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    isRunning = False

            # boardRenderer.startGame(mainWindow, 1, framerate)
        pass


import os
from os.path import join, dirname

from flask import Flask,render_template, request, jsonify
from flask_bootstrap import Bootstrap
from flask_mqtt import Mqtt

from dotenv import load_dotenv

dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)

app = Flask(__name__)
bootstrap = Bootstrap(app)

app.config['MQTT_BROKER_URL'] = os.environ.get('MQTT_BROKER_URL')
app.config['MQTT_BROKER_PORT'] = int(os.environ.get('MQTT_BROKER_PORT'))
app.config['MQTT_USERNAME'] = os.environ.get('MQTT_USERNAME')
app.config['MQTT_PASSWORD'] = os.environ.get('MQTT_PASSWORD')
app.config['MQTT_REFRESH_TIME'] = 1.0  # refresh time in seconds
mqtt = Mqtt(app)

@mqtt.on_connect()
def handle_mqtt_connect(client, userdata, flags, rc):
    mqtt.subscribe('geopose_converter_node/geopose')

@app.route('/')
def index():
    return render_template('index.html')

if __name__ == '__main__':
    app.run(debug=False, host=os.environ.get('APP_IP'), port=os.environ.get('APP_PORT'))


"""requires qtpy"""
import unittest
from pyNastran.gui.menus.about.about import get_packages, get_version, get_shortcuts

class TestMenus(unittest.TestCase):
    def test_about(self):
        """tests the about menu"""
        unused_packages = get_packages()
        unused_version = get_version()
        mouse_shortcuts, keyboard_shortcuts = get_shortcuts()

if __name__ == "__main__":  # pragma: no cover
    import unittest
    unittest.main()


from torch.utils.data import DataLoader
import torch.nn.functional as F
import torch.optim as optim
import torch.nn as nn
import torch

import matplotlib.pyplot as plt
import argparse
import shutil
import time
import os

from torchvf.dataloaders import BPCIS, MultiEpochsDataLoader
from torchvf.losses import IVPLoss, TverskyLoss
from torchvf.transforms import transforms
from torchvf.models import get_model
from torchvf.utils import *

# I am actively looking into a better way to do configs.
from ml_collections.config_flags.config_flags import _ConfigFileParser

parser = argparse.ArgumentParser()
parser.add_argument("--config_dir", default = "./configs/training/bpcis_bact_fluor.py")
args = parser.parse_args()

FileParser = _ConfigFileParser(name = "train")
cfg = FileParser.parse(args.config_dir)

# When using GPU, have this on.
torch.backends.cudnn.benchmark = True

config_dir = os.path.join("./configs", cfg.CONFIG_DIR)
save_to    = next_model(cfg.WEIGHT_DIR)

shutil.copyfile(config_dir, os.path.join(save_to, "config.py"))

########################################
############# DATA LOADER ##############
########################################

train_dataset = BPCIS(
    cfg.DATA.DIR,
    split = cfg.DATA.SPLIT,
    vf = cfg.DATA.VF,
    vf_delimeter = cfg.DATA.VF_DELIM,
    transforms = transforms[cfg.DATA.TRANSFORMS],
    remove = cfg.DATA.REMOVE,
    copy = cfg.DATA.COPY
)

train_dataloader = MultiEpochsDataLoader(
    train_dataset,
    batch_size = cfg.BATCH_SIZE,
    pin_memory = True,
    drop_last = True,
    shuffle = True,
    num_workers = 4
)

########################################
############ MODEL & OPTIM #############
########################################

model = get_model(
    cfg.MODEL_TYPE,
    in_channels = cfg.DATA.C,
    out_channels = [1, 2],
    device = cfg.DEVICE
)

optimizer = optim.Adam(model.parameters(), lr = cfg.LR)

if cfg.PRETRAINED:
    model, optimizer, epoch = load_checkpoint(cfg.PRETRAINED_DIR, model, optimizer)

########################################
############ LOSS FUNCTIONS ############
########################################

vf_losses  = []
sem_losses = []

if cfg.LOSS.IVP.APPLY:
    vf_losses.append([
        "IVP Loss",
        IVPLoss(
            dx = cfg.LOSS.IVP.DX,
            n_steps = cfg.LOSS.IVP.STEPS,
            solver = cfg.LOSS.IVP.SOLVER,
            device = cfg.DEVICE
        )
    ])

if cfg.LOSS.MSE.APPLY:
    vf_losses.append([
        "MSE Loss",
        nn.MSELoss()
    ])

if cfg.LOSS.TVERSKY.APPLY:
    sem_losses.append([
        "Tversky Loss",
        TverskyLoss(
            alpha = cfg.LOSS.TVERSKY.ALPHA,
            beta = cfg.LOSS.TVERSKY.BETA,
            from_logits = cfg.LOSS.TVERSKY.FROM_LOGITS
        )
    ])

if cfg.LOSS.BCE.APPLY:
    sem_losses.append([
        "BCE Loss",
        nn.BCELoss()
    ])

########################################
############### LOGGERS ################
########################################

train_logger = setup_logger("Training",   save_to, filename = "train_log.txt")
delimiter    = " | "

########################################
############ TRAINING LOOP #############
########################################

ITERS = len(train_dataloader)
DEVICE = cfg.DEVICE

model.train(True)
total_time = time.time()
train_logger.info("Starting training.")
for epoch in range(1, cfg.EPOCHS + 1):
    epoch_time = time.time()
    for step, (image, vf, instance_mask) in enumerate(train_dataloader, 1):
        step_time = time.time()

        image         =         image.to(DEVICE, non_blocking = True).float()
        vf            =            vf.to(DEVICE, non_blocking = True).float()
        instance_mask = instance_mask.to(DEVICE, non_blocking = True)

        semantic = torch.where(instance_mask > 0, 1.0, 0.0)

        # Reduces the number of memory operations.
        for param in model.parameters():
            param.grad = None

        pred_semantic, pred_vf = model(image)
#        pred_semantic = torch.sigmoid(pred_semantic)

        loss = 0
        loss_values = []
        for name, loss_f in vf_losses:
            loss_value = loss_f(pred_vf, vf)
            loss_values.append(f"{name}: {loss_value.item():.4f}")
            loss += loss_value

        for name, loss_f in sem_losses:
            loss_value = loss_f(pred_semantic, semantic)
            loss_values.append(f"{name}: {loss_value.item():.4f}")
            loss += loss_value

        loss_values.append(
            f"Total Loss: {loss.item():.4f}"
        )

        loss.backward()
        optimizer.step()

        if step % cfg.LOG.EVERY == 0:
            curr_time = time.time()
            train_logger.info(delimiter.join([
                f"Epoch: [{epoch:>{len(str(cfg.EPOCHS))}}/{cfg.EPOCHS}]",
                f"Step: [{step:>{len(str(ITERS))}}/{ITERS}]",
                f"Step Time: {curr_time - step_time:.4f}",
                f"Total Time: {curr_time - total_time:.4f}",
                *loss_values
            ]))

    # Save the model checkpoint.
    if (epoch == 1) or (epoch % cfg.SAVE_EVERY == 0):
        state = {
            "optimizer_state_dict": optimizer.state_dict(),
            "model_state_dict": model.state_dict(),
            "epoch": epoch
        }

        save_checkpoint(os.path.join(save_to, f"model_{epoch}.pth"), state)

    # Make sure everything looks normal.
    if epoch % cfg.IMAGE_EVERY == 0:
        fig, (ax0, ax1, ax2, ax3) = plt.subplots(1, 4)
        ax0.imshow(pred_vf[0][0].detach().cpu())
        ax1.imshow(pred_vf[0][1].detach().cpu())
        ax2.imshow(image[0][0].detach().cpu())
        ax3.imshow(pred_semantic[0][0].detach().cpu())
        plt.savefig(os.path.join(save_to, f"image_{epoch}.png"), dpi = 400)
        plt.close()


from tempfile import NamedTemporaryFile
import sys
import ujson
import os
import os
from collections import defaultdict as dd
import numpy as np
from itertools import izip
from nltk.corpus.reader import BracketParseCorpusReader
import gzip
import matplotlib
matplotlib.use('Agg')
from nltk.stem import WordNetLemmatizer
from bs4 import BeautifulSoup
import matplotlib.pyplot as plt

def get_stats_from_snli_dataset(files, tagset=("NN", "NNS"), use_lemmas=False):

    lemmatizer = None
    if use_lemmas:
        lemmatizer = WordNetLemmatizer()

    stats = dd(int)
    num_of_token = 0

    for filename in files:
        f = NamedTemporaryFile()
        fields_to_read = {"sentence1_parse", "sentence2_parse"}
        for sent in open(filename):
            sent = ujson.loads(sent)
            for field in fields_to_read:
                f.write("%s\n" % sent[field])

        reader = BracketParseCorpusReader("/tmp", os.path.basename(f.name))
        for word, tag in reader.tagged_words():
            if tagset is None or tag in tagset:
                if use_lemmas:
                    word = lemmatizer.lemmatize(word, pos=tag.lower()[0])
                stats[word] += 1
                num_of_token += 1

    return stats, num_of_token

def get_stats_from_snli_dataset_parsed_by_core_nlp(filename, tagset=("NN", "NNS")):
    stats = dd(int)
    num_of_token = 0
    lemma = None
    for i, line in enumerate(gzip.open(filename)):
        line = line.strip()
        if i % 5000000 == 0:
            print >> sys.stderr, "Processed %d line" % i
        if i % 2 == 0:
            lemma = line[7:-8].lower()
        else:
            tag = line[5:-6]
            if tagset is None or tag in tagset:
                stats[lemma] += 1
                num_of_token += 1

    return stats, num_of_token

def draw_coverage(stats, total, fig_fn, title):
    coverage = [0]
    total = float(total)

    for word, count in stats:
        coverage.append(coverage[-1] + count)

    coverage = np.asarray(coverage) / total
    size = min(len(coverage), 2000)
    plt.figure(figsize=(15, 10))
    plt.plot(range(100, size, 100), coverage[100:size:100], 'o')
    plt.title("Coverage for %s" % title)
    plt.xlabel("# of word used (total # of token = %d)" % total)
    plt.ylabel("Coverage (%)")
    plt.xticks(range(100, size, 100))
    plt.yticks(np.linspace(0.3, 1, 15))
    plt.grid()
    plt.savefig("../../datasets/%s" % fig_fn)

def write_topn_words(stats, total, fn, n=2000):

    total = float(total)
    f = open(fn, 'wb')
    # LOGGER.info("Writing top %d words into the file %s", n, fn)
    for word, count in stats[:n]:
        f.write("{}\t{}\t{}\n".format(word, count, count / total))
    f.close()

def draw_coverage_for_snli_dataset(filename):
    filename = filename
    basename = os.path.basename(filename)
    stats, num_of_token = get_stats_from_snli_dataset_parsed_by_core_nlp(filename)
    fig_fn = "%s.png" % basename
    # LOGGER.info("# of unique word = %d \t # of different token: %d", len(stats), num_of_token
    # )
    stats = sorted(stats.items(), key=lambda t: t[1], reverse=True)
    write_topn_words(stats, num_of_token, "../../datasets/%s.txt" % basename, n=2000)
    draw_coverage(stats, num_of_token, fig_fn, basename)

def main():
    filename = sys.argv[1]
    draw_coverage_for_snli_dataset(filename)

if __name__ == '__main__':
    main()


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

'''
Created on 2019年8月26日

@author: user
'''
import os, sys, logging
from importlib import reload

reload(sys)

PY_GEN_PATH = "D:/data/priv".replace('/', os.sep)
logger = logging.getLogger('pd_dev')
LOG_FILE = 'pd_dev.log'
LOG_FORMATTER = '%(asctime)s - %(filename)s - %(funcName)s - %(lineno)d - %(threadName)s - %(process)d - %(name)s - %(levelname)s - %(message)s'
# LOG_FORMATTER = '%(message)s'

def config_logger():
    logger.setLevel(logging.DEBUG)
    if not os.path.exists(PY_GEN_PATH):
        logger.info("文件夹不存在,已自行创建")
        os.makedirs(PY_GEN_PATH, 777)
    handler = logging.FileHandler(os.path.join(PY_GEN_PATH, LOG_FILE))
    handler.setLevel(logging.DEBUG)
    fmter = logging.Formatter(LOG_FORMATTER)
    handler.setFormatter(fmter)
    logger.addHandler(handler)

    # 控制台打印
    console = logging.StreamHandler()
    console.setLevel(level=logging.DEBUG)  # 设置为INFO级别
    console.setFormatter(fmter)
    logger.addHandler(console)

if __name__ == '__main__':
    config_logger()


# -*- coding: utf-8 -*-
"""
For the one who always believed in me Ankiit Saxena
author: Anujj Saxena
email: saxenaaj@mail.uc.edu
Please feel free to use and modify this, but keep the above information. Thanks!
"""
################################################################
# KALMAN FILTER:
# It is an iterative mathematical process that uses a set of equations and consecutive data inputs to quickly
# estimate the true value, position, velocity of the object being measured. When the measured values contain
# unpredicted or random error, uncertainity or variation.
################################################################
import numpy as np
from numpy import sin, cos, tan, pi, sign
from scipy.integrate import ode
from global_vars import global_vars
import params
import logging
import torch

class neural_net_based_EKF:

    def  __init__(self):
        self.Q = np.identity(9)*0.001
        self.x_hat = np.array([[0], [0], [0], [0], [0], [0], [0], [0], [0]])
        self.P = np.identity(9)

    # ################################################################
    # Predict ######################################################
    # ###############################################################

    # ----------------------------------------------------------------
    # Predict state estimate
    # ---------------------------------------------------------------
    def state_estimate(self, dt, glb):
        # print('t: ',t, 'Ts :' , Ts)
        state = glb.state
        u = state[0]
        v = state[1]
        w = state[2]
        phi = state[3]
        theta = state[4]
        psi = state[5]
        p = state[6]
        q = state[7]
        r = state[8]
        # x_hat = px_hat, py_hat, pz_hat, phi_hat, theta_hat, psi_hat
        x_hat = self.x_hat
        az = -1*state[15]/params.m
        # print(az)

        DynamicsDot = np.array([
                [                                                        u],
                [                                                        v],
                [                                                        w],
                [                                   cos(phi)*sin(theta)*az],
                [                                             -sin(phi)*az],
                [                        params.g + cos(theta)*cos(psi)*az],
                [       p + r*cos(phi)*tan(theta) + q*sin(phi)*tan(theta) ],
                [                                  q*cos(phi) - r*sin(phi)],
                [        (r*cos(phi))/cos(theta) + (q*sin(phi))/cos(theta)]])

        x_hat = x_hat + DynamicsDot*dt
        # print('self.x_hat: ',np.shape(self.x_hat))
        # print('x_hat: ',np.shape(x_hat))
        return x_hat

    #----------------------------------------------------------------
    # Predict covariance estimate
    # ---------------------------------------------------------------
    def covariance_estimate(self, dt, glb, states):
        states = states.detach().numpy()
        state = glb.state
        u = states[3]
        v = states[4]
        w = states[5]
        phi = states[6]
        theta = states[7]
        psi = states[8]
        p = state[6]
        q = state[7]
        r = state[8]
        az = -1*state[15]/params.m
        P = self.P
        # P = np.identity(6)
        Q = self.Q

        F_matrix = np.array([
            [0, 0, 0, 1, 0, 0,                 	 	 0,	 	                  0,  0],
            [0, 0, 0, 0, 1, 0,                  	 0, 	                  0,  0],
            [0, 0, 0, 0, 0, 1,                	     0,     	              0,  0],
            [0, 0, 0, 0, 0, 0, 	sin(phi)*sin(theta)*az,  cos(phi)*cos(theta)*az,  0],
			[0, 0, 0, 0, 0, 0, 			  -1*cos(phi)*az,					  0,  0],
			[0, 0, 0, 0, 0, 0, -1*sin(phi)*cos(theta)*az, cos(phi)*sin(theta)*az, 0],
			[0, 0, 0, 0, 0, 0, q*cos(phi)*tan(theta)-r*sin(phi)*tan(theta), (r*cos(phi)+q*sin(phi))/cos(theta)**2,   0],
            [0, 0, 0, 0, 0, 0,        						   -q*sin(phi),            -r*cos(phi), 			     0],
            [0, 0, 0, 0, 0, 0, (q*cos(phi) - r*sin(phi))/cos(theta), -(q*sin(phi)+r*cos(phi))*tan(theta)/cos(theta), 0]])

        # print(np.dot(F_matrix,P*Ts))
        P_k = P + (np.dot(F_matrix,P) + np.dot(P,F_matrix.transpose()) + Q)*dt
        return P_k

    # ###############################################################
    # Update ######################################################
    # ###############################################################

    #----------------------------------------------------------------
    # Kalman Gain
    # ---------------------------------------------------------------
    def cal_kalman_gain(self, dt, nn_model, x_new, measure, glb):
        # print('pos: ', quad.pos)
            x_hat = self.state_estimate(dt, glb)
            states = nn_model.neural_net_predict(x_new)
        # print('XXHat-shape:  ', x_hat)
            Pk = self.covariance_estimate(dt,glb, states)
        # print('Pk: ', Pk)

        # try:
            C = np.identity(9)
            R = np.identity(9)*0.01
            I = np.identity(9)
            # Y = np.array([[measure[0]], [measure[1]], [measure[2]], [measure[3]], [measure[4]], [measure[5]], [measure[6]], [measure[7]], [measure[8]]])
            Y = np.array([measure[0], measure[1], measure[2], measure[3], measure[4], measure[5], measure[6], measure[7], measure[8]])
            # print(np.dot(np.dot(C,Pk),C.transpose()))
            L = np.nan_to_num(np.dot(np.dot(Pk,C.transpose()),np.linalg.inv(R + np.dot(np.dot(C,Pk),C.transpose()))))  #kalman_gain
            # print(L)
            # logging.info(f'L:{L}')
            self.Pk = np.dot((I - np.dot(L,C)),Pk)
            # print(self.Pk)
            # print(x_hat.detach().numpy())
            # print(np.dot(L, np.transpose(Y - np.transpose(np.dot(C,x_hat)))))
            # foo = (np.transpose(x_hat.detach().numpy()) + np.dot(L,(Y - np.dot(C, x_hat.detach().numpy()))))
            foo = (x_hat + np.dot(L, np.transpose(Y - np.transpose(np.dot(C,x_hat)))))
            # .detach().numpy()
            # print(np.shape(foo))
            # print(np.shape(x_hat))
            nn_model.neural_net_update(torch.from_numpy(foo), torch.from_numpy(x_hat), dt)
            self.x_hat = foo
            glb.kalman_gain_array.append(L)

            return np.transpose(foo), self.Pk
    # ---------------------------------------------------------------


# General imports
import math
import numpy as np

# Keras imports
import keras
from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout, Lambda
from keras.layers.normalization import BatchNormalization
from keras.utils.generic_utils import get_custom_objects
import keras.backend as K

# Helper functions
import load_model_config
import keras_helpers

keras_helpers.define_custom_activations()

def create_model(in_size, out_size, path = "."):
    config = load_model_config.Config(path)

    np.random.seed(config.rand_seed)

    # Optimizer parameters
    if config.opt.name == 'sgd':
      optimizer = keras.optimizers.SGD(lr = config.lr, momentum = config.opt.momentum, nesterov = config.opt.nesterov)
    elif config.opt.name == 'adam':
      epsilon = config.opt.eps_coeff ** config.opt.eps_exp
      optimizer = keras.optimizers.Adam(lr = config.lr, beta_1 = config.opt.beta_1, beta_2 = config.opt.beta_2, epsilon = epsilon, amsgrad = config.opt.amsgrad)

    # Regularizers
    kernel_reg = keras.regularizers.L1L2(l1 = config.kernel_reg.l1, l2 = config.kernel_reg.l2)
    bias_reg = keras.regularizers.L1L2(l1 = config.bias_reg.l1, l2 = config.bias_reg.l2)

    # Hidden layer sizes
    # If n(i) -> n(i+1) is an EQL layer, then n(i) = u + 2v and n(i+1) = u + v.
    # Then, v = n(i) - n(i+1) and u = n(i+1) - v = 2n(i+1) - n(i).
    # Then, for both u > 0 and v > 0, we need n(i+1) < n(i) < 2n(i+1).
    units = (in_size, *[layer.in_units for layer in config.hidden[1:]], out_size)

    # Create the model
    model = Sequential()

    for i in range(len(units) - 1):
        if isinstance(config.hidden[i].act, str):
            # Initializer
            # mean = 0.0
            # stddev = 1 / math.sqrt(units[i])
            # initial = keras.initializers.RandomNormal(mean = mean, stddev = stddev)

            # Hidden layer
            model.add(Dense(units[i + 1], input_shape = (units[i],),
                                          activation = config.hidden[i].act,
                                          kernel_initializer = 'normal',#initial,
                                          bias_initializer = 'normal',#initial,
                                          kernel_regularizer = kernel_reg,
                                          bias_regularizer = bias_reg))
        elif isinstance(config.hidden[i].act, dict) and "eql" in config.hidden[i].act.keys():
            # EQL Layer
            # model.add(Lambda(keras_helpers.eql_activation_twofunc, arguments=kwd_2f1))
            eql_args = {'u': 2 * units[i + 1] - units[i], 'v': units[i] - units[i + 1], 'unary_act': config.hidden[i].act['eql']}
            model.add(Lambda(keras_helpers.eql_activation, arguments = eql_args))

        if config.hidden[i].norm:
            model.add(BatchNormalization())
        if config.hidden[i].dropout:
            model.add(Dropout(config.dropout))

    # Configure the model for training
    model.compile(optimizer = optimizer, loss = config.loss, metrics = config.metrics)

    return model


class Tools:
    @staticmethod
    def get_id_from_message(message):
        return message.from_user.username

    @staticmethod
    def is_text_correct(text, real, bot_username):
        return text == real or text == (bot_username + " " + real)

    @staticmethod
    def time_from_seconds(time):
        hours = time // 3600
        time %= 3600
        minutes = time // 60
        time %= 60
        return str(hours // 10) + str(hours % 10) + ":" + str(minutes // 10) + str(minutes % 10) + ":" + str(
            time // 10) + str(time % 10)

    @staticmethod
    def get_time_to_string(time):
        if time == "00:00:00":
            return ""
        else:
            return str("через " + time)


# import random
# import string
import csv
from datetime import datetime

import stripe
from django.conf import settings
from django.contrib import messages
from django.core.exceptions import ObjectDoesNotExist
from django.shortcuts import redirect, render
from django.views import View
from django.views.generic.detail import DetailView
from django.views.generic.list import ListView

from .forms import (CheckoutForm, CouponForm, PaymentForm, RefundForm,
                    ShopItemsUploadForm)
from .models import (Address, Category, Coupon, Item, Order, OrderItem,
                     Payment, Refund, ShopProfile)
from .utils import (add_to_cart, is_valid_form,
                    remove_from_cart, remove_single_item_from_cart, upload_shop_data)

stripe.api_key = settings.STRIPE_SECRET_KEY

# TODO: Create User Profile view, prepopulate forms with all user data
# TODO: Search functionality for shop items
# TODO: Fix Pagination to include page numbers either side of current page on Home and category pages
# TODO: Fix select category links to become active when on that page
# TODO: Add link to item page on item in cart
# TODO: Create request refund functionality

class HomeView(ListView):
    model = Item
    template_name = 'shop/home.html'
    context_object_name = 'items'
    paginate_by = 10

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['categories'] = Category.objects.all()
        context['hero_header'] = 'Amazing Life'
        return context

class ProductView(DetailView):
    model = Item
    template_name = 'shop/product.html'
    context_object_name = 'item'

class CategoryListView(ListView):
    model = Category
    template_name = "shop/category_list.html"
    context_object_name = 'categories'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['hero_header'] = 'Categories'
        return context

class CategoryDetailView(DetailView):
    model = Category
    template_name = "shop/category_detail.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        category = Category.objects.get(slug=self.kwargs['slug'])
        context['items'] = Item.objects.filter(
            category=category)
        context['categories'] = Category.objects.all()
        context['hero_header'] = category.title
        return context

class CheckoutView(View):
    def get(self, request, *args, **kwargs):
        # Check profile exists
        try:
            profile = ShopProfile.objects.get(user=request.user)
        except ObjectDoesNotExist:
            messages.info(request, 'You do not have a shop profile')
            return redirect('shop:home')
        # Check order exists
        try:
            order = Order.objects.get(user=profile, ordered=False)
            form = CheckoutForm()
            order_items = OrderItem.objects.filter(order=order, ordered=False)
            context = {
                'order': order,
                'form': form,
                'order_items': order_items,
                'coupon_form': CouponForm()
            }

            if profile.shipping_address:
                context.update(
                    {'default_shipping_address': profile.shipping_address})

            if profile.billing_address:
                context.update(
                    {'default_billing_address': profile.billing_address})

            return render(request, 'shop/checkout.html', context)

        except ObjectDoesNotExist:
            messages.info(request, 'You do not have an active order')
            return redirect('shop:home')

    # TODO: Set logic when changing address to current in CheckoutView POST method
    # TODO: Fix order billing/shipping address when order is made
    def post(self, request, *args, **kwargs):
        try:
            # Get user profile
            profile = ShopProfile.objects.get(user=request.user)
        except ObjectDoesNotExist:
            messages.info(request, 'No shop profile exists')
            return redirect('shop:home')
        try:
            order = Order.objects.get(user=profile, ordered=False)

            # Get form info, add info to order
            form = CheckoutForm(request.POST or None)
            if form.is_valid():
                # Check if using default shipping and default billing address from form
                use_default_shipping = form.cleaned_data.get(
                    'use_default_shipping')
                use_default_billing = form.cleaned_data.get(
                    'use_default_billing')
                same_billing_address = form.cleaned_data.get(
                    'same_billing_address')

                # Shipping Address Logic
                if use_default_shipping:
                    if profile.shipping_address:
                        order_shipping_address = profile.shipping_address
                        order.shipping_address = order_shipping_address
                        order.save()
                    else:
                        messages.info(
                            request, 'No default shipping address available')
                        return redirect('shop:checkout')
                else:
                    # Make new shipping address for order
                    shipping_address_1 = form.cleaned_data.get(
                        'shipping_address_1')
                    shipping_address_2 = form.cleaned_data.get(
                        'shipping_address_2')
                    shipping_country = form.cleaned_data.get(
                        'shipping_country')
                    shipping_zip_code = form.cleaned_data.get(
                        'shipping_zip_code')

                    if is_valid_form([shipping_address_1, shipping_country, shipping_zip_code]):
                        order_shipping_address = Address(
                            user=profile,
                            address_line_1=shipping_address_1,
                            address_line_2=shipping_address_2,
                            country=shipping_country,
                            zip_code=shipping_zip_code,
                            address_type='S'
                        )
                        order_shipping_address.save()
                        order.shipping_address = order_shipping_address
                        order.save()

                        # set default shipping if user checked set default in form
                        set_default_shipping = form.cleaned_data.get(
                            'set_default_shipping')
                        if set_default_shipping:
                            profile.shipping_address = order_shipping_address
                    else:
                        messages.info(
                            request, 'Please fill in the required shipping address fields')
                        return redirect('shop:checkout')
                if same_billing_address and use_default_shipping:
                    order_billing_address = Address(
                        user=profile,
                        address_line_1=profile.shipping_address.address_line_1,
                        address_line_2=profile.shipping_address.address_line_2,
                        country=profile.shipping_address.country,
                        zip_code=profile.shipping_address.zip_code,
                        address_type='B'
                    )
                    order.billing_address = profile.billing_address
                    order.save()
                # Billing Address Logic
                elif use_default_billing:
                    if profile.billing_address:
                        order.billing_address = profile.billing_address
                        order.save()
                    else:
                        messages.info(
                            request, 'No default billing address available')
                        return redirect('shop:checkout')
                elif same_billing_address:
                    order_billing_address = Address(
                        user=profile,
                        address_line_1=order_shipping_address.address_line_1,
                        address_line_2=order_shipping_address.address_line_2,
                        country=order_shipping_address.country,
                        zip_code=order_shipping_address.zip_code,
                        address_type='B'
                    )
                    order_billing_address.address_type = 'B'
                    order_billing_address.save()
                    order.billing_address = order_billing_address
                # User is entering in new address
                else:
                    billing_address_1 = form.cleaned_data.get(
                        'billing_address_1')
                    billing_address_2 = form.cleaned_data.get(
                        'billing_address_2')
                    billing_country = form.cleaned_data.get(
                        'billing_country')
                    billing_zip_code = form.cleaned_data.get(
                        'billing_zip_code')
                    # Check form is not empty, cant use form because fields are not required in model
                    if is_valid_form([billing_address_1, billing_country, billing_zip_code]):
                        order_billing_address = Address(
                            user=profile,
                            address_line_1=billing_address_1,
                            address_line_2=billing_address_2,
                            country=billing_country,
                            zip_code=billing_zip_code,
                            address_type='B'
                        )
                        order_billing_address.save()
                        order.billing_address = order_billing_address
                        order.save()
                        # set default billing if user checked set default in form
                        set_default_billing = form.cleaned_data.get(
                            'set_default_billing')
                        if set_default_billing:
                            if set_default_billing:
                                profile.billing_address = order_billing_address
                    else:
                        messages.info(
                            request, 'Please fill in the required billing address fields')
                        return redirect('shop:checkout')

                profile.current_order = order
                profile.save()

                # Check payment option and redirect as needed
                payment_option = form.cleaned_data.get('payment_option')
                if payment_option == 'stripe' or 'cash' or 'paypal':
                    return redirect('shop:payment', payment_option=payment_option)
                else:
                    messages.info(
                        request, 'Bad Payment option')
                    return redirect('shop:home')

            # Bad form input
            else:
                messages.warning(
                    request, 'There was an error while processing your input')
                return redirect('shop:checkout')
        except ObjectDoesNotExist:
            messages.info(request, 'You do not have an active order')
            return redirect('shop:home')

class PaymentView(View):
    def get(self, request, *args, **kwargs):
        # Check order exists
        try:
            profile = ShopProfile.objects.get(user=request.user)
        except ObjectDoesNotExist:
            messages.info(request, 'You do not have a shop profile')
            return redirect('shop:home')
        try:
            order = Order.objects.get(
                user=profile, ordered=False)
            order_items = OrderItem.objects.filter(order=order, ordered=False)
            if order.billing_address:
                # Check payment option
                payment_option = self.kwargs['payment_option']
                if payment_option == 'stripe' or 'cash' or 'paypal':
                    context = {
                        'order': order,
                        'order_items': order_items,
                        'show_cart_coupon': False,
                        'payment_option': payment_option
                    }

                    if profile.one_click_purchasing:
                        cards = stripe.Customer.list_sources(
                            profile.stripe_cutomer_id,
                            limit=3,
                            object='card'
                        )
                        card_list = cards['data']
                        if len(card_list) > 0:
                            context.update({'card': card_list[0]})
                    return render(request, 'shop/payment.html', context)
                # bad form input
                else:
                    messages.warning(
                        request, 'Bad payment option choice')
                    return redirect('shop:home')
            else:
                messages.warning(
                    request, 'You have not added a billing address')
                return redirect('shop:checkout')
        except ObjectDoesNotExist:
            messages.info(request, 'You do not have an active order')
            return redirect('shop:home')

    def post(self, request, *args, **kwargs):
        # Check order exists
        try:
            profile = ShopProfile.objects.get(user=request.user)
        except ObjectDoesNotExist:
            messages.info(request, 'You do not have a shop profile')
            return redirect('shop:home')
        try:
            order = Order.objects.get(
                user=profile, ordered=False)
            # Check form is valid
            form = PaymentForm(request.POST)

            if form.is_valid():
                save = form.cleaned_data.get('save')
                token = form.cleaned_data.get('stripeToken')
                use_default = form.cleaned_data.get('use_default')

                if save:
                    if not profile.stripe_customer_id:
                        customer = stripe.Customer.crate(
                            email=request.user.profile.email,
                            source=token
                        )
                        profile.stripe_cutomer_id = customer['id']
                        profile.one_click_purchasing = True
                        profile.save()
                    else:
                        stripe.Customer.create_source(
                            profile.stripe_customer_id,
                            source=token
                        )

                amount = int(order.get_total())
                payment = Payment()
                payment.user = profile
                payment.amount = amount

                # Cash payment
                if self.kwargs['payment_option'] == 'cash':
                    payment_option = 'cash'

                # Stripe payment
                elif self.kwargs['payment_option'] == 'stripe':
                    payment_option = 'stripe'
                    if use_default:
                        charge = stripe.Charge.create(
                            amount=amount,
                            currency='usd',
                            source=profile.stripe_customer_id
                        )
                    else:
                        charge = stripe.Chrage.create(
                            amount=amount,
                            currency='usd',
                            source=token
                        )

                # Paypal payment
                elif self.kwargs['payment_option'] == 'paypal':
                    messages.info(request, 'PAYPAL')
                    return redirect('shop:home')

                else:
                    messages.info(request, 'Incorrect payment method')
                    return redirect('shop:home')

                # Save payment add to order
                payment.payment_option = payment_option
                payment.ref_code = order.ref_code
                payment.save()
                order.payment = payment
                order.ordered_date = datetime.now()
                order.ordered = True
                order.save()
                profile.current_order = None
                profile.save()

                # update order items to ordered = true
                order_items = OrderItem.objects.filter(
                    order=order, ordered=False)
                order_items.update(ordered=True)
                for item in order_items:
                    item.save()

                # TODO: Add coupon to user profile redeemed coupons
                # profile.redeemend_coupons.add(coupon)
                # TODO: Send email to admin  and user on payment submit

                messages.info(request, 'Order successful')
                return redirect('shop:home')
            else:
                messages.info(request, 'Invalid form input')
                return redirect('shop:home')

        except ObjectDoesNotExist:
            messages.info(request, 'You do not have an active order')
            return redirect('shop:home')

class OrderSummaryView(View):
    def get(self, request, *args, **kwargs):
        try:
            order = Order.objects.get(
                user=request.user.shopprofile, ordered=False)
            order_items = OrderItem.objects.filter(order=order, ordered=False)
            context = {
                'order': order,
                'order_items': order_items
            }
            return render(request, 'shop/order_summary.html', context)
        except ObjectDoesNotExist:
            return render(request, 'shop/order_summary.html')

class RequestRefundVew(View):
    def get(self, request, *args, **kwargs):
        form = RefundForm()
        context = {
            'form': form
        }
        return render(request, 'shop/request_refund.html', context)

    def post(self, request, *args, **kwargs):
        form = RefundForm(request.POST)
        if form.is_valid():
            ref_code = form.cleaned_data.get('ref_code')
            message = form.cleaned_data.get('message')
            email = form.cleaned_data.get('email')
            try:
                order = Order.objects.get(ref_code=ref_code)
                order.refund_requested = True
                order.save()
                refund = Refund(order=order)
                refund.reason = message
                refund.email = email
                refund.ref_code = order.ref_code
                refund.username = request.user.profile.username
                refund.save()
                messages.info(request, ' Your request has been received')
                return redirect('shop:request_refund')

                # TODO: Send  email to admin on refund request in RequestRefundView POST method

            except ObjectDoesNotExist:
                messages.info(request, 'You do not have an active order')
                return redirect('shop:request_refund')

        else:
            messages.info(request, 'Invalid form input')
            return redirect('shop:request_refund')

class UploadShopItems(View):
    def get(self, request, *args, **kwargs):

        form = ShopItemsUploadForm()
        context = {'form': form}
        return render(request, "shop/csv_form.html", context)

    def post(self, request, *args, **kwargs):
        form = ShopItemsUploadForm(request.POST, request.FILES or None)
        if form.is_valid():
            file = request.FILES['csv_file']
            # Check iif CSV file
            if not file.name.endswith('.csv'):
                messages.info(request, 'This s not a CSV file')
                return redirect('admin:shop_item_changelist')
            # Upload csv file function in shop/utisl.py
            if upload_shop_data(file):
                messages.info(request, 'File successfully uploaded')
                return redirect('admin:shop_item_changelist')
            else:
                # TODO: Improve upload_shop_data error checking in shop/views.py
                messages.warning(request, 'File upload unsucessful')
                return redirect('admin:shop_item_changelist')
        else:
            messages.info(request, 'Invalid file format')
            return redirect('admin:shop_item_changelist')


from models import TimeSlot, Schedule
from utils import get_sorted_mean
from ga import GeneticAlgorithm
from constraints.soft_constraints import calculate_penalty_of_student
from read_data import read_student_and_course_data

NUMBER_OF_DAYS = 12
SLOTS_PER_DAY = 3
NUM_OF_RUNNING = 10

def test_different_params(path_to_input_file: str, num_of_days: int = NUMBER_OF_DAYS):
    professors: list[str] = []

    courses, students = read_student_and_course_data(path_to_input_file)

    time_slots: list[TimeSlot] = [TimeSlot(id) for id in range(num_of_days * SLOTS_PER_DAY)]
    population_sizes: list[int] = [i for i in range(100, 601, 100)]
    max_generations: list[int] = [i for i in range(100, 301, 100)]
    mutation_probs: list[float] = [i/10 for i in range(4, 10)]

    path_to_output_file: str = ''.join(path_to_input_file.split('.')[:-1]) + '_output.txt'
    output_file = open(path_to_output_file, 'w')
    output_file.write(f'population_size max_generation mutation_prob')

    for population_size in population_sizes:
        for max_generation in max_generations:
            for mutation_prob in mutation_probs:

                output_file.write(f'\n{population_size} {max_generation} {mutation_prob}\n')

                print(population_size, max_generation, mutation_prob)

                for _ in range(NUM_OF_RUNNING):
                    genetic_algo: GeneticAlgorithm = GeneticAlgorithm(population_size=population_size,
                                                                      max_generation=max_generation,
                                                                      mutation_probability=mutation_prob,
                                                                      courses=courses,
                                                                      students=students,
                                                                      professors=professors,
                                                                      time_slots=time_slots,
                                                                      time_slot_per_day=SLOTS_PER_DAY,
                                                                      calculate_penalty_of_student=
                                                                      calculate_penalty_of_student
                                                                      )
                    schedule: Schedule = genetic_algo.generate_schedule()

                    output_file.write(f'{schedule.fitness} ')

    output_file.close()

    get_sorted_mean(path_to_output_file)


"""
Tests for all functionality of the Session object
"""

# Third Party
import pytest

# First Party
import aconfig

# Local
from oper8.patch import STRATEGIC_MERGE_PATCH
from oper8.session import MAX_NAME_LEN, Session
from oper8.status import make_application_status
from oper8.test_helpers.helpers import (
    DummyNodeComponent,
    MockDeployManager,
    make_patch,
    setup_cr,
)

## Helpers #####################################################################

def make_component_class(comp_name):
    class DerivedComponent(DummyNodeComponent):
        name = comp_name

    return DerivedComponent

def make_api_obj(
    kind="Foo",
    api_version="foo.bar/v1",
    name="foo",
    namespace="testit",
):
    return aconfig.Config(
        {
            "kind": kind,
            "apiVersion": api_version,
            "metadata": {
                "name": name,
                "namespace": namespace,
                "labels": {"app": "test", "run": name},
            },
        },
        override_env_vars=False,
    )

## Tests #######################################################################

###############
## Prperties ##
###############

def test_constructed_properties():
    """Make sure all properties derived from the constructor args are populated
    correctly
    """
    rec_id = "1ab"
    cr = setup_cr()
    cfg = aconfig.Config({"foo": "bar"}, override_env_vars=False)
    dm = MockDeployManager()
    patches = [make_patch(STRATEGIC_MERGE_PATCH, {})]
    session = Session(rec_id, cr, cfg, dm, patches)
    assert session.id == rec_id
    assert session.cr_manifest == cr
    assert session.config == cfg
    assert session.deploy_manager == dm
    assert session.temporary_patches == patches

def test_cr_properties():
    """Make sure all properties derived from the CR manifest are populated
    correctly
    """
    version = "develop.1.2.3"
    namespace = "wingbat"
    name = "wombat"
    api_version = "critters.bats/v23"
    kind = "Critter"
    spec = {"key": "value"}
    cr = setup_cr(
        api_version=api_version,
        kind=kind,
        namespace=namespace,
        name=name,
        version=version,
        spec=spec,
    )
    session = Session("1ab", cr, {}, MockDeployManager())
    assert session.version == version
    assert session.namespace == namespace
    assert session.name == name
    assert session.kind == kind
    assert session.api_version == api_version
    assert session.spec == cr.spec
    assert session.metadata == cr.metadata

@pytest.mark.parametrize(
    "field",
    ["kind", "apiVersion", "metadata", "metadata.name", "metadata.namespace"],
)
def test_missing_cr_required_fields(field):
    """Make sure that required fields missing from the CR correctly raise
    validation errors
    """
    cr = setup_cr()
    field_parts = field.split(".")
    dct = cr
    while len(field_parts) > 1:
        dct = dct[field_parts[0]]
        field_parts = field_parts[1:]
    del dct[field_parts[0]]
    with pytest.raises(AssertionError):
        session = Session("1ab", cr, {}, MockDeployManager())

@pytest.mark.parametrize(
    "field,expected",
    [("spec", aconfig.Config({})), ("spec.version", None)],
)
def test_missing_cr_optional_fields(field, expected):
    """Make sure that optional fields in the CR that are accessed via properties
    do not raise errors
    """
    cr = setup_cr()
    field_parts = field.split(".")
    dct = cr
    while len(field_parts) > 1:
        dct = dct[field_parts[0]]
        field_parts = field_parts[1:]
    del dct[field_parts[0]]
    session = Session("1ab", cr, {}, MockDeployManager())
    assert getattr(session, field.split(".")[-1]) == expected

def test_current_version():
    """Make sure that retrieving the current_version works when it's present
    in the deploy manager
    """
    # Make sure that current_version is not set when it hasn't been deployed
    cr = setup_cr()
    dm = MockDeployManager()
    session = Session("1ab", cr, {}, dm)
    assert session.current_version is None

    # Make sure that current_version is set when it's been deployed before
    current_version = "some-version"
    cr.status = make_application_status(version=current_version)
    dm.deploy([cr])
    session = Session("2cd", cr, {}, dm)
    assert session.current_version == current_version

def test_dict_conversion():
    """Make sure that a CR as a raw dict is converted (for that 100% cov!)"""
    Session("1ab", dict(setup_cr()), {}, MockDeployManager())

######################
## State Management ##
######################

def test_add_component_ok():
    """Make sure that add_component successfully adds enabled and disabled
    components
    """
    session = Session("1ab", setup_cr(), {}, MockDeployManager())
    enabled_comp = make_component_class("enabled")(session)
    disabled_comp = make_component_class("disabled")(session, disabled=True)
    assert session.get_components() == [enabled_comp]
    assert session.get_components(disabled=True) == [disabled_comp]

def test_add_component_no_duplicate():
    """Make sure that the same component cannot be added multiple times"""
    session = Session("1ab", setup_cr(), {}, MockDeployManager())
    CompType = make_component_class("comp")
    CompType(session)
    with pytest.raises(ValueError):
        CompType(session)

def test_add_component_dependency_ok():
    """Make sure that adding a dependency from one component to another works as
    expected
    """
    session = Session("1ab", setup_cr(), {}, MockDeployManager())
    comp1 = make_component_class("one")(session)
    comp2 = make_component_class("two")(session)
    session.add_component_dependency(comp1, comp2)
    assert session.get_component_dependencies(comp1.name) == [(comp2, None)]

def test_add_component_dependency_verify_function():
    """Make sure that adding a dependency with a verify function stores the
    verify function successfully
    """
    session = Session("1ab", setup_cr(), {}, MockDeployManager())
    comp1 = make_component_class("one")(session)
    comp2 = make_component_class("two")(session)
    verify_fn = lambda *_, **__: True
    session.add_component_dependency(comp1, comp2, verify_function=verify_fn)
    dep_list = session.get_component_dependencies(comp1.name)
    assert len(dep_list) == 1
    assert dep_list[0][0] == comp2
    assert dep_list[0][1].func == verify_fn

def test_add_component_dependency_by_name():
    """Make sure that adding a dependency can be done by name"""
    session = Session("1ab", setup_cr(), {}, MockDeployManager())
    comp1 = make_component_class("one")(session)
    comp2 = make_component_class("two")(session)
    session.add_component_dependency(comp1.name, comp2.name)
    assert session.get_component_dependencies(comp1.name) == [(comp2, None)]

def test_add_component_dependency_no_unknown_component():
    """Make sure that a dependency can't be added for an unknown component"""
    session = Session("1ab", setup_cr(), {}, MockDeployManager())
    comp2 = make_component_class("two")(session)
    with pytest.raises(ValueError):
        session.add_component_dependency("one", comp2)

def test_add_component_dependency_no_unknown_upstream():
    """Make sure that a dependency can't be added for an unknown upstream"""
    session = Session("1ab", setup_cr(), {}, MockDeployManager())
    comp1 = make_component_class("one")(session)
    with pytest.raises(ValueError):
        session.add_component_dependency(comp1, "two")

def test_add_component_dependency_no_disabled_component():
    """Make sure that a dependency can't be added for a disabled component"""
    session = Session("1ab", setup_cr(), {}, MockDeployManager())
    enabled_comp = make_component_class("enabled")(session)
    disabled_comp = make_component_class("disabled")(session, disabled=True)
    with pytest.raises(ValueError):
        session.add_component_dependency(disabled_comp, enabled_comp)

def test_add_component_dependency_no_disabled_upstream():
    """Make sure that a dependency can't be added for a disabled upstream"""
    session = Session("1ab", setup_cr(), {}, MockDeployManager())
    enabled_comp = make_component_class("enabled")(session)
    disabled_comp = make_component_class("disabled")(session, disabled=True)
    with pytest.raises(ValueError):
        session.add_component_dependency(enabled_comp, disabled_comp)

###############
## Utilities ##
###############

def test_get_scoped_name():
    """Make sure that get_scoped_name correctly scopes and truncates"""
    name = "some-name"
    dm = MockDeployManager()
    session = Session("1ab", setup_cr(name=name), {}, dm)

    # Test a name shorter than the max length
    assert session.get_scoped_name("foo") == f"{name}-foo"

    # Test a name longer than the max length
    scoped_name = session.get_scoped_name(
        "".join((str(i % 10) for i in range(MAX_NAME_LEN)))
    )
    assert len(scoped_name) == MAX_NAME_LEN
    assert scoped_name.startswith(name)

def test_get_truncated_name():
    """Make sure that get_truncated_name correctly (only) truncates"""
    name = "some-name"
    dm = MockDeployManager()
    session = Session("1ab", setup_cr(name=name), {}, dm)

    # Test a name shorter than the max length
    assert session.get_truncated_name("foo") == "foo"

    # Test a name longer than the max length
    long_name = "".join((str(i % 10) for i in range(MAX_NAME_LEN * 2)))
    trunc_name = session.get_truncated_name(long_name)
    assert len(trunc_name) == MAX_NAME_LEN
    assert not trunc_name.startswith(name)

    # Test that truncation makes names unique when the instance name is longer
    # than the max
    session = Session("1ab", setup_cr(name=long_name), {}, dm)
    assert session.get_truncated_name("foo") != session.get_truncated_name("bar")

def test_get_object_current_state():
    """Make sure that get_object_current_state correctly proxies to the deploy
    manager with the current namespace
    """
    dm = MockDeployManager()
    session = Session("1ab", setup_cr(), {}, dm)
    obj1 = make_api_obj(namespace=session.namespace)
    obj2 = make_api_obj(namespace="different-namespace", name="other-name")
    dm.deploy([obj1, obj2])

    # Make sure it fetches correctly with api_version in the same namespace
    success, obj1_state = session.get_object_current_state(
        kind=obj1.kind,
        api_version=obj1.apiVersion,
        name=obj1.metadata.name,
    )
    assert success
    assert obj1_state == obj1

    # Make sure it fetches correctly without api_version in the same namespace
    success, obj1_state = session.get_object_current_state(
        kind=obj1.kind,
        name=obj1.metadata.name,
    )
    assert success
    assert obj1_state == obj1

    # Make sure it doesn't find objects in different namespaces
    success, obj2_state = session.get_object_current_state(
        kind=obj2.kind,
        api_version=obj2.apiVersion,
        name=obj2.metadata.name,
    )
    assert success
    assert obj2_state is None

def test_filter_objects_current_state():
    """Make sure that filter_object_current_state correctly proxies to the deploy
    manager with the current namespace
    """
    dm = MockDeployManager()
    session = Session("1ab", setup_cr(), {}, dm)
    obj1 = make_api_obj(namespace=session.namespace, name="first")
    obj2 = make_api_obj(namespace=session.namespace, name="second")
    obj3 = make_api_obj(namespace="different-namespace", name="other-name")
    dm.deploy([obj1, obj2, obj3])

    # Make sure it fetches correctly in the same namespace
    success, obj_list = session.filter_objects_current_state(
        kind=obj1.kind,
        api_version=obj1.apiVersion,
    )
    assert success
    assert len(obj_list) == 2
    assert obj1 in obj_list and obj2 in obj_list

    # Make sure it fetches correctly filters labels
    success, obj_list = session.filter_objects_current_state(
        kind=obj1.kind, label_selector="run=first"
    )
    assert success
    assert len(obj_list) == 1
    assert obj_list[0] == obj1

    # Make sure it fetches correctly filters fields
    success, obj_list = session.filter_objects_current_state(
        kind=obj1.kind, field_selector="metadata.name!=first"
    )
    assert success
    assert len(obj_list) == 1
    assert obj_list[0] == obj2

    # Make sure it doesn't find objects in different namespaces
    success, obj_list = session.filter_objects_current_state(
        kind=obj2.kind, field_selector="metadata.name=other-name"
    )
    assert success
    assert len(obj_list) == 0


from ctypes import alignment
from tkinter.messagebox import NO
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from enum import Enum
import datetime
from dateutil.relativedelta import relativedelta
import pandas as pd
from pyparsing import col

from evaluation.db import *
from evaluation.constant import *
import warnings

warnings.filterwarnings("ignore")

plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False

__all__ = [
    'line_name',
    'plot',
    'plot_index_list',
    'plot_line_list',
    'plot_long_pe_percent',
    'plot_short_pe_percent',
    'plot_long_pb_percent',
    'plot_short_pb_percent',
    'plot_position',
    ]

class line_name(Enum):
    close = 'close'
    pe  = 'pe'

    close_5day_mean = 'close_5day_mean'
    close_10day_mean = 'close_10day_mean'
    close_20day_mean = 'close_20day_mean'
    close_1year_mean = 'close_1year_mean'

    pe_1year_percent = 'pe_1year_percent'
    pe_3year_percent = 'pe_3year_percent'
    pe_5year_percent = 'pe_5year_percent'
    pe_10year_percent = 'pe_10year_percent'
    pe_history_percent = 'pe_history_percent'

    pb_1year_percent = 'pb_1year_percent'
    pb_3year_percent = 'pb_3year_percent'
    pb_5year_percent = 'pb_5year_percent'
    pb_10year_percent = 'pb_10year_percent'
    pb_history_percent = 'pb_history_percent'

# 左y轴为close
def plot(df_local, line_list,
                    start_date = None, end_date = None,
                    left_y_min = None, left_y_max = None,
                    right_y_min = None, right_y_max = None,
                    right_y_interval = None):
    fig=plt.figure(figsize=(20,8), dpi=300)
    fig.set_facecolor('white')

    #绘制第一个Y轴
    ax=fig.add_subplot(111)
    lin0=ax.plot(df_local.index, df_local['close'], color="r", label="close")
    ax.set_title("Evaluation", size=12)
    ax.set_xlabel("date", size=12)
    ax.set_ylabel("close", size=12)
    ax.grid(axis='x')
    if start_date is not None and end_date is not None:
        ax.set_xlim([start_date, end_date])
    if left_y_max is not None and left_y_min is not None:
        ax.set_ylim([left_y_min, left_y_max])

    colors = [
        'xkcd:light blue',
        'xkcd:pink',
        'xkcd:turquoise',
        'xkcd:lavender',
        'xkcd:peach'
            ]

    #绘制另一Y轴
    ax1=ax.twinx()
    for i in range(len(line_list)):
        linx = ax1.plot(df_local[line_list[i].value], color=colors[i % len(colors)], label=line_list[i].value)
        lin0=lin0+linx

    ax1.grid()
    if right_y_interval is not None:
        ax1.yaxis.set_major_locator(ticker.MultipleLocator(right_y_interval))
    ax1.set_ylabel("value", size=12)
    if right_y_max is not None and right_y_min is not None:
        ax1.set_ylim([right_y_min, right_y_max])

    #合并图例
    labs=[l.get_label() for l in lin0]
    ax.legend(lin0, labs, loc="upper left", fontsize=12)

    plt.show()

def plot_index_list(indexs, line,
        start_date = None, end_date = None,
        y_min = None, y_max = None,
        y_interval = None):
    fig=plt.figure(figsize=(20,8), dpi=300)
    fig.set_facecolor('white')

    #绘制第一个Y轴
    ax=fig.add_subplot(111)
    ax.set_title(line.value, size=12)
    ax.set_xlabel("date", size=12)
    ax.set_ylabel(line.value, size=12)
    ax.grid(axis='x')
    ax.grid()

    if start_date is not None and end_date is not None:
        ax.set_xlim([start_date, end_date])

    if y_interval is not None:
        ax.yaxis.set_major_locator(ticker.MultipleLocator(y_interval))

    if y_max is not None and y_min is not None:
        ax.set_ylim([y_min, y_max])

    lines = None
    for i in range(len(indexs)):
        df_local = load_local_db_by_filename(indexs[i], period='month')
        l = ax.plot(df_local.index, df_local[line.value], color='C' + str(i % 10), label=line.value)
        if lines is None:
            lines = l
        else:
            lines = lines + l

    #合并图例
    ax.legend(lines, indexs, loc="upper left", fontsize=12)

    plt.show()

def plot_line_list(df_local, line_list,
        start_date = None, end_date = None,
        y_min = None, y_max = None,
        y_interval = None):
    fig=plt.figure(figsize=(20,8), dpi=300)
    fig.set_facecolor('white')

    #绘制第一个Y轴
    ax=fig.add_subplot(111)
    ax.set_xlabel("date", size=12)
    ax.grid(axis='x')
    ax.grid()

    if start_date is not None and end_date is not None:
        ax.set_xlim([start_date, end_date])

    if y_interval is not None:
        ax.yaxis.set_major_locator(ticker.MultipleLocator(y_interval))

    if y_max is not None and y_min is not None:
        ax.set_ylim([y_min, y_max])

    lines = None
    for i in range(len(line_list)):
        l = ax.plot(df_local.index, df_local[line_list[i].value], color='C' + str(i % 10), label=line_list[i].value)
        if lines is None:
            lines = l
        else:
            lines = lines + l

    #合并图例
    labs=[l.get_label() for l in lines]
    ax.legend(lines, labs, loc="upper left", fontsize=12)

    plt.show()

# 左y轴：close
# 右y轴：各年份pe百分比
# x轴：2000-至今
def plot_long_pe_percent(index_name):
    df_local = load_local_db(index_name, period='month')

    plot(df_local,
            [line_name.pe_3year_percent, line_name.pe_5year_percent, line_name.pe_10year_percent, line_name.pe_history_percent],
            start_date=datetime.date(2000, 1, 1), end_date=datetime.datetime.now().date(),
            right_y_min=0.0, right_y_max=1.0, right_y_interval=0.05)

# 左y轴：close
# 右y轴：各年份pe百分比
# x轴：近一年
def plot_short_pe_percent(index_name):
    df_local = load_local_db(index_name, period='month')

    plot(df_local,
        [line_name.pe_3year_percent, line_name.pe_5year_percent, line_name.pe_10year_percent, line_name.pe_history_percent],
        start_date=datetime.datetime.now()-relativedelta(years=1), end_date=datetime.datetime.now().date(),
        right_y_min=0.0, right_y_max=1.0, right_y_interval=0.05)

# 左y轴：close
# 右y轴：各年份pb百分比
# x轴：2000-至今
def plot_long_pb_percent(index_name):
    df_local = load_local_db(index_name, period='month')

    plot(df_local,
            [line_name.pb_3year_percent, line_name.pb_5year_percent, line_name.pb_10year_percent, line_name.pb_history_percent],
            start_date=datetime.date(2010, 1, 1), end_date=datetime.datetime.now().date(),
            right_y_min=0.0, right_y_max=1.0, right_y_interval=0.05)

# 左y轴：close
# 右y轴：各年份pb百分比
# x轴：近一年
def plot_short_pb_percent(index_name):
    df_local = load_local_db(index_name, period='month')
    plot(df_local,
        [line_name.pb_3year_percent, line_name.pb_5year_percent, line_name.pb_10year_percent, line_name.pb_history_percent],
        start_date=datetime.datetime.now()-relativedelta(years=1), end_date=datetime.datetime.now().date(),
        right_y_min=0.0, right_y_max=1.0, right_y_interval=0.05)

def plot_position(cash, security):
    df = load_position(cash, security)
    size = 0.3

    colors_list = [
        '#5a86ad',
        '#cb416b',
        '#de7e5d',
        '#56ae57',
        '#d5b60a',
        '#95a3a6'
        ]
    color_dict = {}
    dic1 = {'name' : [], 'sum' : [], 'color' : []}
    dic2 = {'name' : [], 'sum' : [], 'color' : []}
    dic3 = {'name' : [], 'sum' : [], 'color' : []}

    for i in range(len(df)):
        row = df.iloc[i]
        if (row['L1'] not in dic1['name']):
            dic1['name'].append(row['L1'])
            dic1['sum'].append(0)
            dic1['color'].append(colors_list[(len(dic1['name']) - 1) % len(colors_list)])
        idx1 = dic1['name'].index(row['L1'])
        dic1['sum'][idx1] += row['position']
        color = dic1['color'][idx1]

        if (row['L2'] not in dic2['name']):
            dic2['name'].append(row['L2'])
            dic2['sum'].append(0)
            dic2['color'].append(color)
        idx2 = dic2['name'].index(row['L2'])
        dic2['sum'][idx2] += row['position']

        if (row['L3'] not in dic3['name']):
            dic3['name'].append(row['L3'])
            dic3['sum'].append(0)
            dic3['color'].append(color)
        idx3 = dic3['name'].index(row['L3'])
        dic3['sum'][idx3] += row['position']

    fig=plt.figure(figsize=(8,8), dpi=300)
    fig.set_facecolor('white')
    ax=fig.add_subplot(111)

    def my_label(dic1):
        labels = []
        sum = 0
        for i in range(len(dic1['name'])):
            sum += dic1['sum'][i]
        for i in range(len(dic1['name'])):
            labels.append("{:s}\n{:.1f}%".format(dic1['name'][i], dic1['sum'][i] / sum * 100))
        return labels

    ax.pie(dic3['sum'], radius=4 * size, colors=dic3['color'], labels=my_label(dic3), labeldistance=0.85, rotatelabels=True, counterclock=False, startangle=90,
            textprops=dict(color="w", fontsize=6, ha='center', va='center'),
            wedgeprops=dict(width=size, edgecolor='w', linewidth=0.2))
    ax.pie(dic2['sum'], radius=3 * size, colors=dic2['color'], labels=my_label(dic2), labeldistance=0.8, rotatelabels=True, counterclock=False, startangle=90,
            textprops=dict(color="w", fontsize=6, ha='center', va='center'),
            wedgeprops=dict(width=size, edgecolor='w', linewidth=0.2))
    ax.pie(dic1['sum'], radius=2 * size, colors=dic1['color'], labels=my_label(dic1), labeldistance=0.7, rotatelabels=True, counterclock=False, startangle=90,
            textprops=dict(color="w", fontsize=6, ha='center', va='center'),
            wedgeprops=dict(width=size, edgecolor='w', linewidth=0.2))

    plt.show()


import logging
import binascii
from datetime import datetime

from flask import  request
from webargs import fields, validate
from webargs.flaskparser import parser
import ujson
from app.api_1_0 import api
from app.decorator import json
from app.src.subscription import Subscription

logger = logging.getLogger()

@api.route("/subscription/<pageno>/<pagesize>", methods=["GET"])
@json
def get_subscription_list(pageno, pagesize):
    pageno = int(pageno)
    pagesize = int(pagesize)

    offset = (pageno-1) * pagesize
    limit = pagesize

    subscription_list, total_records = Subscription().get_detailed_list(limit, offset)
    for subscription in subscription_list:
        subscription['uuid'] = binascii.hexlify(subscription['uuid'])
        subscription['variant']['uuid'] = binascii.hexlify(subscription['variant']['uuid'])

    result = {'total_records':total_records, 'data':subscription_list}
    return result

@api.route("/subscription/<subscription_id>", methods=["GET"])
@json
def get_subscription_by_id(subscription_id):
    sub = Subscription(subscription_id)
    subscription = sub.get_details()
    subscription['uuid'] = binascii.hexlify(subscription['uuid'])
    subscription['variant']['uuid'] = binascii.hexlify(subscription['variant']['uuid'])
    logger.debug(subscription)
    return subscription

@api.route("/subscription", methods=["POST"])
@json
def create_subscription():
    subscription_args = {
        "variant_id"                : fields.Int(required=True),
        "seller_id"                 : fields.Int(required=True),
        "transfer_price"            : fields.Float(required=True),
        "take_rate"                 : fields.Float(required=True),
        "seller_indicated_price"    : fields.Float(required=True),
        "quantity_available"        : fields.Int(required=True),
        "valid_from"                : fields.Str(required=True),
        "valid_thru"                : fields.Str(required=True),
        "status_id"                 : fields.Int(required=True)
    }
    logger.debug(request.data)
    args = parser.parse(subscription_args, request)
    subscription = Subscription().create_subscription(args)
    subscription['uuid'] = binascii.hexlify(subscription['uuid'])
    return subscription

@api.route("/subscription", methods=["PUT"])
@json
def update_subscription():
    subscription_args = {
        "id"                        : fields.Int(required=True),
        "variant_id"                : fields.Int(required=False),
        "seller_id"                 : fields.Int(required=False),
        "transfer_price"            : fields.Float(required=False),
        "take_rate"                 : fields.Float(required=False),
        "seller_indicated_price"    : fields.Float(required=False),
        "quantity_available"        : fields.Int(required=False),
        "valid_from"                : fields.Str(required=False),
        "valid_thru"                : fields.Str(required=False),
        "status_id"                 : fields.Int(required=False)
    }
    logger.debug(request.data)
    args = parser.parse(subscription_args, request)
    logger.debug(args)
    data = args
    id = data["id"]
    del(data["id"])

    updated_subscription = Subscription(id).update(data)
    updated_subscription['uuid'] = binascii.hexlify(updated_subscription['uuid'])
    return updated_subscription

@api.route("/subscription/<subscription_id>/condition", methods=["GET"])
@json
def get_conditions_by_subscription_by_id(subscription_id):
    subscription = Subscription(subscription_id)
    conditions = subscription.get_conditions()
    return conditions

@api.route("/subscription/<subscription_id>/condition", methods=["POST"])
@json
def attach_condition_to_subscription(subscription_id):
    condition_args = {
        "condition_id"  : fields.Int(required=True),
        "status_id"     : fields.Int(required=True)
    }
    logger.debug(request.data)
    args = parser.parse(condition_args, request)
    logger.debug(args)
    subscription = Subscription(subscription_id)
    conditions = subscription.attach_condition(args)
    return conditions

@api.route("/subscription/<subscription_id>/serviceable_geo", methods=["GET"])
@json
def get_serviceable_geos_by_subscription_by_id(subscription_id):
    subscription = Subscription(subscription_id)
    serviceable_geos = subscription.get_serviceable_geos()
    return serviceable_geos

@api.route("/subscription/<subscription_id>/serviceable_geo", methods=["POST"])
@json
def attach_serviceable_geo_to_subscription(subscription_id):
    serviceable_geo_args = {
        "geo_id"        : fields.Int(required=True),
        "serviceability": fields.Str(required=True, validate=lambda v: v in ['hub', 'direct']),
        "status_id"     : fields.Int(required=True)
    }
    logger.debug(request.data)
    args = parser.parse(serviceable_geo_args, request)
    logger.debug(args)
    subscription = Subscription(subscription_id)
    serviceable_geos = subscription.attach_serviceable_geo(args)
    return serviceable_geos

@api.route("/subscription/<subscription_id>/serviceable_geo/<serviceable_geo_id>/shipping", methods=["GET"])
@json
def get_serviceable_geo_shipping_by_subscription_by_id(subscription_id, serviceable_geo_id):
    subscription = Subscription(subscription_id)
    serviceable_geo_shippings = subscription.get_serviceable_geo_shippings(serviceable_geo_id)
    return serviceable_geo_shippings

@api.route("/subscription/<subscription_id>/serviceable_geo/<serviceable_geo_id>/shipping", methods=["POST"])
@json
def attach_serviceable_geo_shipping_to_subscription(subscription_id, serviceable_geo_id):
    serviceable_geo_shipping_args = {
        "shipping_type_id"  : fields.Int(required=True),
        "shipping_charge"   : fields.Float(required=True),
        "valid_from"        : fields.Str(required=True),
        "valid_thru"        : fields.Str(required=True),
        "status_id"         : fields.Int(required=True)
    }
    logger.debug(request.data)
    args = parser.parse(serviceable_geo_shipping_args, request)
    logger.debug(args)
    subscription = Subscription(subscription_id)
    serviceable_geo_shippings = subscription.attach_serviceable_geo_shipping(serviceable_geo_id, args)
    return serviceable_geo_shippings


# https://github.com/iiiiiii1/douban-imdb-api

from src.helper import get_request

def search_with_wmdb(query, limit=10, skip=0, lang='Cn', year=None):
    url = "https://api.wmdb.tv/api/v1/movie/search?q=" + query + "&limit=" + str(limit) + "&skip=" + str(skip) + "&lang=" + lang
    if year:
        url += "&year=" + year
    return get_request("wmdb", url)

def get_wmdb_movie_detail(douban_id):
    url = "https://api.wmdb.tv/movie/api?"
    url += "id=" + douban_id

    return get_request("wmdb", url)

def organize_wmdb_data(movie, movie_detail):
    movie.title = movie_detail['data'][0]['name']
    movie.original_title = movie_detail['originalName']
    movie.director = [movie_detail['director'][x]['data'][0]['name'] for x in range(len(movie_detail['director']))]
    movie.cast = [movie_detail['actor'][x]['data'][0]['name'] for x in range(len(movie_detail['actor']))][:5]
    movie.genre = movie_detail['data'][0]['genre'].split('/')
    movie.region = movie_detail['data'][0]['country'].split(',')
    movie.release_date = movie_detail['dateReleased']
    movie.poster_url = movie_detail['data'][0]['poster']


from django.urls import path, include
from django.conf import settings
from rest_framework.routers import DefaultRouter
from . import views

router = DefaultRouter()
router.include_root_view = False
router.register('address', views.UserAddressViewSet)
router.register('express', views.ExpressViewSet)
router.register('delivery', views.DeliveryAddressViewSet)
router.register('order', views.OrdersViewSet)
router.register('item', views.ItemsViewSet)

urlpatterns = [
    path('wechatpay/', views.Wechatpay.as_view(), name='wechatpay'),
    path('468468418416846841684a6efaefa/', views.PayCallback.as_view(), name='paycallback'),
    path('pull_pay_result/', views.PullPayResult.as_view(), name='pull-pay-result'),
    path('cancel_order/', views.CancelOrder.as_view(), name='cance_lorder'),
    path('confirm_receipt/', views.ConfirmReceipt.as_view(), name='confirm_receipt'),
    path('cartbuy/', views.CartBuyView.as_view(), name='cartbuy'),
    path('replace/', views.ReplaceGoodsView.as_view(), name='replace'),
    path('batch-export/', views.ExportBatchDeliveryView.as_view(), name='batch-export'),
    path('batch-export-query/', views.QueryBatchDeliveryView.as_view(), name='batch-export-query'),
    path('', include(router.urls)),
]


import requests
from email.utils import parsedate_to_datetime

URL = "http://training.securitum.com/rozwal/podstawowka/podstawowka_2.php"

from hashlib import md5
def md5_file(filename):
    crc = md5()
    fp = open(filename, 'rb')
    for i in fp:
        crc.update(i)
    fp.close()
    return crc.hexdigest()
params={}
files={}
def pretty_print_POST(req):
    """
    At this point it is completely built and ready
    to be fired; it is "prepared".

    However pay attention at the formatting used in
    this function because it is programmed to be pretty
    printed and may differ from the actual request.
    """
    print('{}\n{}\n{}\n\n{}'.format(
        '-----------START-----------',
        req.method + ' ' + req.url,
        '\n'.join('{}: {}'.format(k, v) for k, v in req.headers.items()),
        req.body,
    ))
params = {'ROZWAL':md5_file('ROZWAL.txt')}
files = {'ROZWAL': open('ROZWAL.txt', 'rb')}
r = requests.post(URL, params=params, files=files)
pretty_print_POST(r.request)
print(r.text)


import streamlit as st
import pandas as pd
import joblib

# Load model
prophet_model = joblib.load('prophet_model.joblib')

# Prediction Function
def predict_future_month(prophet_model, input_month):
    future_month_df = pd.DataFrame({'ds': [input_month]})
    future_month_forecast = prophet_model.predict(future_month_df)
    predicted_value = future_month_forecast['yhat'].values[0]
    return predicted_value

month_map = {
    "January": 1, "February": 2, "March": 3, "April": 4, "May": 5, "June": 6,
    "July": 7, "August": 8, "September": 9, "October": 10, "November": 11, "December": 12
}

st.title('Future Total Receipt Prediction')

# Inputs

input_year = st.selectbox("Select a year", options=[2021,2022,2023], index=1)
input_month_name = st.selectbox("Select a month", options=["January", "February", "March", "April", "May", "June",
                                                           "July", "August", "September", "October", "November", "December"],
                                                           index=0)

if st.button("Submit"):
    if input_month_name in month_map:
        input_month = month_map[input_month_name]

        # Use the Prophet model to make predictions for the input month
        future_month_df = pd.DataFrame({'ds': [pd.to_datetime(f"{input_year}-{input_month:02}")]})
        future_month_forecast = prophet_model.predict(future_month_df)

        # Extract predicted value, upper, and lower confidence intervals
        predicted_value = future_month_forecast['yhat'].values[0]
        upper_confidence = future_month_forecast['yhat_upper'].values[0]
        lower_confidence = future_month_forecast['yhat_lower'].values[0]

        # Round the values to the nearest tenths
        rounded_predicted_value = round(predicted_value, 0)
        rounded_upper_confidence = round(upper_confidence, 0)
        rounded_lower_confidence = round(lower_confidence, 0)

        # Display the prediction in a table
        result_data = {
            "Month": input_month_name,
            "Year": str(input_year),
            "Predicted Values": [rounded_predicted_value],
            "Upper Confidence Interval": [rounded_upper_confidence],
            "Lower Confidence Interval": [rounded_lower_confidence]
        }
        result_df = pd.DataFrame(result_data)
        st.write(result_df)

    else:
        st.error("Invalid selection. Please choose a valid month.")


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

from sklearn.preprocessing import StandardScaler

def calculateMSE(X,Y,theta):
    Y_pred = np.dot(X,theta)
    error = Y_pred - Y
    squareError = np.square(error)
    sumSquareError = np.sum(squareError)
    dim = Y.shape[0]
    dim *= 2 #Multiplying by half
    MSE = sumSquareError / dim
    return MSE

def calculateGradient(X,Y,theta):
    yPredict = np.dot(X,theta)
    error = yPredict - Y
    xTranspose = X.transpose()
    gradient = np.dot(xTranspose,error)
    return gradient

data = pd.read_csv('Fish.csv')
X = data[['Length1','Length2','Length3','Height','Width']]
X_bias = np.ones((X.shape[0], 1)) # 159
X_new = np.append(X_bias, X, axis=1)

Y = data['Weight']
X_new = np.array(X_new)

Y = np.array(Y)

Y = np.reshape(Y,(Y.shape[0],1)) # (159,1)

theta = np.zeros((6,1))
sc = StandardScaler()
X_new = sc.fit_transform(X_new)
maxIter = 100
tolerance = 0.0000000001
alpha = 0.01
errors = []
iterations = []
for i in range(maxIter):
    curCost = calculateMSE(X_new,Y,theta)
    if (i+1) % 10 == 0:
        errors.append(curCost)
        iterations.append(i)
    if curCost < tolerance:
        break
    gradient = calculateGradient(X_new,Y,theta)
    theta = theta - alpha* (gradient/Y.shape[0])

print(errors)
plt.plot(iterations,errors)
plt.xlabel('Iteration')
plt.ylabel('Error')
plt.title('Gradient Descent')
plt.show()


import openai
import re
from approaches.approach import Approach
from azure.search.documents import SearchClient
from azure.search.documents.models import QueryType
from langchain.llms.openai import AzureOpenAI
from langchain.prompts import PromptTemplate, BasePromptTemplate
from langchain.callbacks.manager import CallbackManager
from langchain.agents import Tool, AgentExecutor
from langchain.agents.react.base import ReActDocstoreAgent
from langchainadapters import HtmlCallbackHandler
from text import nonewlines
from typing import List

class ReadDecomposeAsk(Approach):
    def __init__(self, search_client: SearchClient, openai_deployment: str, sourcepage_field: str, content_field: str):
        self.search_client = search_client
        self.openai_deployment = openai_deployment
        self.sourcepage_field = sourcepage_field
        self.content_field = content_field

    def search(self, q: str, overrides: dict) -> str:
        use_semantic_captions = True if overrides.get("semantic_captions") else False
        top = overrides.get("top") or 3
        exclude_category = overrides.get("exclude_category") or None
        filter = "category ne '{}'".format(exclude_category.replace("'", "''")) if exclude_category else None

        if overrides.get("semantic_ranker"):
            r = self.search_client.search(q,
                                          filter=filter,
                                          query_type=QueryType.SEMANTIC,
                                          query_language="en-us",
                                          query_speller="lexicon",
                                          semantic_configuration_name="default",
                                          top = top,
                                          query_caption="extractive|highlight-false" if use_semantic_captions else None)
        else:
            r = self.search_client.search(q, filter=filter, top=top)
        if use_semantic_captions:
            self.results = [doc[self.sourcepage_field] + ":" + nonewlines(" . ".join([c.text for c in doc['@search.captions'] ])) for doc in r]
        else:
            self.results = [doc[self.sourcepage_field] + ":" + nonewlines(doc[self.content_field][:500]) for doc in r]
        return "\n".join(self.results)

    def lookup(self, q: str) -> str:
        r = self.search_client.search(q,
                                      top = 1,
                                      include_total_count=True,
                                      query_type=QueryType.SEMANTIC,
                                      query_language="en-us",
                                      query_speller="lexicon",
                                      semantic_configuration_name="default",
                                      query_answer="extractive|count-1",
                                      query_caption="extractive|highlight-false")

        answers = r.get_answers()
        if answers and len(answers) > 0:
            return answers[0].text
        if r.get_count() > 0:
            return "\n".join(d['content'] for d in r)
        return None

    def run(self, q: str, overrides: dict) -> any:
        # Not great to keep this as instance state, won't work with interleaving (e.g. if using async), but keeps the example simple
        self.results = None

        # Use to capture thought process during iterations
        cb_handler = HtmlCallbackHandler()
        cb_manager = CallbackManager(handlers=[cb_handler])

        llm = AzureOpenAI(deployment_name=self.openai_deployment, temperature=overrides.get("temperature") or 0.3, openai_api_key=openai.api_key)
        tools = [
            Tool(name="Search", func=lambda q: self.search(q, overrides), description="useful for when you need to ask with search", callbacks=cb_manager),
            Tool(name="Lookup", func=self.lookup, description="useful for when you need to ask with lookup", callbacks=cb_manager)
        ]

        # Like results above, not great to keep this as a global, will interfere with interleaving
        global prompt
        prompt_prefix = overrides.get("prompt_template")
        prompt = PromptTemplate.from_examples(
            EXAMPLES, SUFFIX, ["input", "agent_scratchpad"], prompt_prefix + "\n\n" + PREFIX if prompt_prefix else PREFIX)

        agent = ReAct.from_llm_and_tools(llm, tools)
        chain = AgentExecutor.from_agent_and_tools(agent, tools, verbose=True, callback_manager=cb_manager)
        result = chain.run(q)

        # Replace substrings of the form <file.ext> with [file.ext] so that the frontend can render them as links, match them with a regex to avoid
        # generalizing too much and disrupt HTML snippets if present
        result = re.sub(r"<([a-zA-Z0-9_ \-\.]+)>", r"[\1]", result)

        return {"data_points": self.results or [], "answer": result, "thoughts": cb_handler.get_and_reset_log()}

class ReAct(ReActDocstoreAgent):
    @classmethod
    def create_prompt(cls, tools: List[Tool]) -> BasePromptTemplate:
        return prompt

# Modified version of langchain's ReAct prompt that includes instructions and examples for how to cite information sources
EXAMPLES = [
    """Question: Which type of data should be sent from video cameras in a native binary format?
Select only one answer.
A) structured
B) semi-structured
C) unstructured
Answer: Video data should be sent from video cameras in a native binary format. As mentioned in source 1, binary data is used to store images, video, audio, and application-specific documents. Video data is a type of unstructured data that is typically stored in its native binary format.
Citations:
1. \[Explore file storage - Training _ Microsoft Learn-2.pdf\]""",
]
SUFFIX = """\nQuestion: {input}
{agent_scratchpad}"""
PREFIX = "You are my test proctor. Test me on Azure Data Fundamentals also known as DP-900. " \
        "Ask one multiple choice question and allow me to answer before asking the next question. " \
        "Each question must have a minimum of three choices and a maximum of five choices." \
        "If the answer is wrong, provide the correct answer and ask the next question. " \
        "Answer ONLY with the facts listed in the list of sources below. " \
        "If there isn't enough information below, say you don't know. " \
        "Do not generate answers that don't use the sources below. " \
        "If asking a clarifying question to the user would help, ask the question. " \
        "Each source has a name followed by colon and the actual data, quote the source name for each piece of data you use in the response. " \
        "Use square brakets to reference the source, e.g. [info1.txt]. Don't combine sources, list each source separately, e.g. [info1.txt][info2.pdf]." \
        "Do not generate answers that don't use the sources below. If asking a clarifying question to the user would help, ask the question. " \
        "Answer the question using only the data provided in the information sources below. " \
        "For tabular information return it as an html table. Do not return markdown format. " \
        "For example, if the question is \"What color is the sky?\" and one of the information sources says \"info123: the sky is blue whenever it's not cloudy\", then answer with \"The sky is blue [info123]\" " \
        "It's important to strictly follow the format where the name of the source is in square brackets at the end of the sentence, and only up to the prefix before the colon (\":\"). " \
        "If there are multiple sources, cite each one in their own square brackets. For example, use \"[info343][ref-76]\" and not \"[info343,ref-76]\". " \
        "Never quote tool names as sources." \
        "If you cannot answer using the sources below, say that you don't know. " \


import cv2
import numpy as np
import face_recognition

# my module
import utils
import unibo_face as uf
from inception_blocks_v2 import faceRecoModel

def main():

    model = uf.initModel()
    database = uf.initDatabase(model)

    CAP = cv2.VideoCapture(0)

    while True:
        isRead, frame = CAP.read()
        if isRead:
            frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
            frame = cv2.resize(frame, (640, 360))
            uf.process_frame(frame, database, model)
            frame = cv2.cvtColor(frame, cv2.COLOR_RGB2BGR)
            cv2.imshow("Display", frame)

        if cv2.waitKey(1) & 0xFF == ord('q'):
            break

    CAP.release()
    cv2.destroyAllWindows()

if __name__ == '__main__':
    main()


# -*- coding: utf-8 -*-
"""
Created on Sat May  9 00:54:53 2020

@author: IVAALEX
"""
from datetime import datetime

class TimeUtility(object):
    NULL_TIME = "%d:%02d:%02d" % (0, 0, 0)
    def __init__(self):
        pass

    def addTimes(self, time1, time2):
        timeList = [ time1, time2]
        totalSecs = 0
        for tm in timeList:
            timeParts = [int(s) for s in str(tm).split(':')]
            #timeParts = [tm.hour, tm.minute, tm.second]
            totalSecs += (timeParts[0] * 60 + timeParts[1]) * 60 + timeParts[2]
        totalSecs, sec = divmod(totalSecs, 60)
        hr, min = divmod(totalSecs, 60)
        return "%d:%02d:%02d" % (hr, min, sec)

    def convertToDecimal(self, time):
        timeParts = [int(s) for s in str(time).split(':')]
        totalSecs = (timeParts[0] * 60 + timeParts[1]) * 60 + timeParts[2]
        decimalTime = totalSecs / 3600
        return round(decimalTime,2)

if __name__ == '__main__':
    tu = TimeUtility()
    time1 = "01:15:00"
    print(tu.convertToDecimal(time1))


# -*- coding: utf-8 -*-
# @Time    : 2020/6/10/0010 16:20
# @Author  : Aqi
# @File    : requests_handler.py
# @Software: PyCharm

import requests
import logging
import traceback

def visit(url, method='get', params=None, data=None, json=None, **kwargs):
    try:
        res = requests.request(method, url, params=params, data=data, json=json, **kwargs)
        return res
    except Exception as e:
        logging.error(e)
        logging.error(traceback.format_exc())
        raise e


#User function Template for python3

class Solution:
    def distinctColoring (self, N, r, g, b):
        # code here
        dp = [[0 for i in range(3)] for i in range(N)]

        dp[0][0] = r[0]
        dp[0][1] = g[0]
        dp[0][2] = b[0]

        for i in range(1, N):

            dp[i][0] = min(dp[i-1][1], dp[i-1][2]) + r[i]
            dp[i][1] = min(dp[i-1][0], dp[i-1][2]) + g[i]
            dp[i][2] = min(dp[i-1][0], dp[i-1][1]) + b[i]

        return min(dp[N-1][0], dp[N-1][1], dp[N-1][2])

#{
 # Driver Code Starts
#Initial Template for Python 3

if __name__ == '__main__':
    t = int (input ())
    for _ in range (t):
        N = int(input())
        r = list(map(int, input().split()))
        g = list(map(int, input().split()))
        b = list(map(int, input().split()))

        ob = Solution()
        print(ob.distinctColoring(N, r, g, b))
# } Driver Code Ends


#백준 숨바꼭질

import heapq

def solution() :
    n,k = map(int,input().split())

    queue = [[0,n]]
    visited = [False]*100001
    count = 0
    while queue :
        front = queue.pop(0)
        # print(front)

        if not visited[front[1]] :

            visited[front[1]] = True
            count = front[0]

            if front[1] == k :
                return count

            count += 1

            if front[1]+1 <= 100000 :
                heapq.heappush(queue, [count, front[1] + 1])
            if front[1]-1 >= 0 :
                heapq.heappush(queue, [count, front[1] - 1])
            if front[1]*2 <= 100000 :
                heapq.heappush(queue, [count, front[1] * 2])

    return count

print(solution())