#!/user/bin/env python
# -*- coding: utf-8 -*-
from deeplearning.nn.interface.nn_builder import NNBuilder
from deeplearning.synapse.neural_network_graph import NeuralNetworkGraph
from deeplearning.activation.interface.activating_function_interface import ActivatingFunctionInterface

class NNDirector(object):
    '''
    GoFのデザイン・パタンの「Builder Pattern」の「監督者」
    パーセプトロンのシナプスを組み立てることで、
    ニューラルネットワークのオブジェクトを生成する
    '''

    # GoFのデザイン・パタンの「Bulder Pattern」の「建築者」
    __nn_builder = None
    # ニューラルネットワークのリスト
    __nn_list = []

    def get_nn_list(self):
        ''' getter '''
        if isinstance(self.__nn_list, list) is False:
            raise TypeError()

        for nn in self.__nn_list:
            if isinstance(nn, NeuralNetworkGraph) is False:
                raise TypeError()

        return self.__nn_list

    def set_nn_list(self, value):
        ''' setter '''
        if isinstance(value, list) is False:
            raise TypeError()

        for nn in value:
            if isinstance(nn, NeuralNetworkGraph) is False:
                raise TypeError()

        self.__nn_list = value

    nn_list = property(get_nn_list, set_nn_list)

    def __init__(self, nn_builder):
        '''
        「建築者」を初期化する

        Args:
            nn_builder     Builder Patternの「具体的な建築者」
        '''
        if isinstance(nn_builder, NNBuilder) is False:
            raise TypeError()

        self.__nn_builder = nn_builder

    def nn_construct(
        self,
        neuron_assign_list,
        activating_function_list
    ):
        '''
        ニューラルネットワークを構築する

        Args:
            neuron_assign_list:          各層のニューロンの個数のリスト
            activating_function_list:    活性化関数のリスト
        '''
        if len(activating_function_list) != len(neuron_assign_list):
            raise ValueError()

        for activating_function in activating_function_list:
            if isinstance(activating_function, ActivatingFunctionInterface) is False:
                raise TypeError()

        input_neuron_count = neuron_assign_list[0]
        input_activating_function = activating_function_list[0]
        output_neuron_count = neuron_assign_list[-1]
        output_activating_function = activating_function_list[-1]

        self.__nn_builder.input_neuron_part(
            input_activating_function,
            input_neuron_count
        )

        for i in range(1, len(neuron_assign_list) - 1):
            hidden_neuron_count = neuron_assign_list[i]
            hidden_activating_function = activating_function_list[-1]
            self.__nn_builder.hidden_neuron_part(
                hidden_activating_function,
                hidden_neuron_count
            )

        self.__nn_builder.output_neuron_part(
            output_activating_function,
            output_neuron_count
        )

        self.__nn_builder.graph_part()

        self.nn_list = self.__nn_builder.get_result()


import bug_memory as memory
import matplotlib.pyplot as plt
from google_vision_api import requestLabel

#Decision Node
def decision(image):
    [label, score] = requestLabel(image) # Output of API converted into a label and a score
    print("Oooooh that's a", label, ". I'm", score, "percent sure!")
    params = memory.getValue(label) # Array of paramaters [alpha, beta,  survival, ex alpha, ex beta]
    # return alpha = coward coefficient; beta = aggressor coefficient
    alpha = params[0]; beta = params[1]
    return alpha, beta, label

def error(totalTime, label):
    # We calculate our error based on the change in Survival Time = Duration 1000 sec
    # if survival time decreases
    #    error = (old time - new time)/total
    #    if error is -ve --> Positive stimulus (Survival Time Has Increased)
    #           increase beta and decrease alpha
    #    if error is +ve --> Negative stimulus (Survival Time Has Decreased)
    #           increase alpha and decrease beta
    params = memory.getValue(label)
    delta = -1*params[2]
    print(delta)
    survivalAdjustment = (delta)/(totalTime)
    # if delta = -100  and totalTime = 1000 error should be 0.1
    return survivalAdjustment, delta

def update_error(error,label):
    # Array of paramaters [alpha, beta,  survival, ex alpha, ex beta]
    memory.adjustValue(label, error)

image = 'Images/7.jpg'
alpha, beta, label = decision(image)
print('alpha: ', alpha)
print('beta: ', beta)
print('label: ', label)
print('####################  Starting Simulation ############################')
totalTime = 1000;
[survivalAdjustment, timeAdjustment]= error(totalTime, label)
print('Error: ', survivalAdjustment, timeAdjustment)
update_error(survivalAdjustment,label)
params = memory.getValue(label)
print('alpha: ', params[0])
print('beta: ', params[1])
print('######iteration 2#############')
print(memory.getValue('spider'))
update_error(survivalAdjustment,label)
print(memory.getValue('spider'))


# !/usr/bin/env python

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import logging
import sys
import random
import datetime

import numpy as np
import scipy as scp
import scipy.misc
import tensorflow as tf

import fcn16_vgg
import utils

RESOURCE = '../dataset'
MODEL_PATH = "./models/model-250-5-10.ckpt"

# Boundary, route, obstacle.
colors = [[243, 193, 120], [0, 168, 120], [254, 94, 65]]

logging.basicConfig(format='%(asctime)s %(levelname)s %(message)s',
                    level=logging.INFO,
                    stream=sys.stdout)

dataset = utils.read_files(RESOURCE)
random.shuffle(dataset)
input_set, output_set = utils.split_dataset(dataset)

height = input_set.shape[1]
width = input_set.shape[2]
num_classes = 3

input_placeholder = tf.placeholder(tf.float32, [None, height, width, num_classes])
output_placeholder = tf.placeholder(tf.float32, [None, height, width, num_classes])

vgg_fcn = fcn16_vgg.FCN16VGG('./vgg16.npy')

with tf.name_scope("content_vgg"):
    vgg_fcn.build(input_placeholder, train=True, num_classes=num_classes)

print('Finished building Network.')

# Initializing the variables.
init = tf.global_variables_initializer()

# Saver op to save and restore all the variables
saver = tf.train.Saver()

# With CPU mini-batch size can be bigger.
with tf.device('/cpu:0'):
    config = tf.ConfigProto(allow_soft_placement=True)
    config.gpu_options.allow_growth = True

    with tf.Session(config=config) as sess:
        # Restore model weights from previously saved model.
        saver.restore(sess, MODEL_PATH)

        print('Running the Network')

        prediction = sess.run(vgg_fcn.pred_up, feed_dict={input_placeholder: [input_set[0]]})

        # Original image mixed with predicted image.
        regions_image = utils.regions_to_colored_image(prediction[0], colors)
        merged_image = utils.merge_images(input_set[0], regions_image, 0.65)

        current_time = datetime.datetime.now()
        scp.misc.imsave(str(current_time) + ' prediction.png', prediction[0])
        scp.misc.imsave(str(current_time) + ' input.png', input_set[0])
        scp.misc.imsave(str(current_time) + ' output.png', output_set[0])
        scp.misc.imsave(str(current_time) + ' merged.png', merged_image)


import MySQLdb as mdb
con = mdb.connect('localhost', 'root', '_PW_', 'iggeqadb');
with con:
	cur = con.cursor()
	cur.execute('DROP TABLE IF EXISTS tblLabs')
	cur.execute('CREATE TABLE tblLabs (labID INT PRIMARY KEY AUTO_INCREMENT, \
			labName VARCHAR(25), \
			vcFileShare VARCHAR(256), \
			localFileShare VARCHAR(256), \
			active	BOOLEAN not null default 0, \
			comment VARCHAR(512))')


from enum import Enum
import numbers
import numpy as np

from expyriment.misc import geometry

#--------------------------------------------------------------------------
class ErrMsg(object):

    _invalid_attr_type = "trajtracker error: invalid attempt to set {0}.{1} to a non-{2} value ({3})"
    _set_to_non_positive = "trajtracker error: invalid attempt to set {0}.{1} to a non-positive value ({2})"
    _set_to_negative = "trajtracker error: invalid attempt to set {0}.{1} to a negative value ({2})"
    _set_to_invalid_value = "trajtracker error: {0}.{1} was set to an invalid value ({2})"

    @staticmethod
    def attr_invalid_type(class_name, attr_name, expected_type, arg_value):
        return "trajtracker error: {0}.{1} was set to a non-{2} value ({3})".format(class_name, attr_name, expected_type, arg_value)

    @staticmethod
    def attr_invalid_value(class_name, attr_name, arg_value):
        "trajtracker error: {0}.{1} was set to an invalid value ({2})".format(class_name, attr_name, arg_value)

    @staticmethod
    def invalid_method_arg_type(class_name, method_name, expected_type, arg_name, arg_value):
        return "trajtracker error: {0}.{1}() was called with a non-{2} {3} ({4})".format(class_name, method_name, expected_type, arg_name, arg_value)

#============================================================================
#   Validate attributes
#============================================================================

NoneValues = Enum("NoneValues", "Invalid Valid ChangeTo0")

#--------------------------------------
def _get_type_name(t):

    if not isinstance(t, type):
        t = type(t)

    if isinstance(t, (list, tuple, np.ndarray)):
        return "/".join([_get_type_name(tt) for tt in t])
    elif t == numbers.Number:
        return "number"
    elif t == np.ndarray:
        return "array"
    else:
        return t.__name__

#--------------------------------------
def validate_attr_type(obj, attr_name, value, attr_type, none_allowed=False, type_name=None):

    if (value is None and not none_allowed) or (value is not None and not isinstance(value, attr_type)):
        if type_name is None:
            type_name = _get_type_name(attr_type)

        raise TypeError(ErrMsg.attr_invalid_type(_get_type_name(obj), attr_name, type_name, value))

#--------------------------------------
def validate_attr_anylist(obj, attr_name, value, min_length=None, max_length=None, none_allowed=False):

    if value is None and none_allowed:
        value = ()

    validate_attr_type(obj, attr_name, value, (list, tuple, np.ndarray), type_name="list/tuple")
    if min_length is not None and len(value) < min_length:
        raise TypeError(
            "trajtracker error: {:}.{:} cannot be assigned to a collection with {:} elements - a minimal of {:} elements are expected".
            format(_get_type_name(obj), attr_name, len(value), min_length))

    if max_length is not None and len(value) > max_length:
        raise TypeError(
            "trajtracker error: {:}.{:} cannot be assigned to a collection with {:} elements - a maximum of {:} elements is allowed".
            format(_get_type_name(obj), attr_name, len(value), max_length))

    return value

#--------------------------------------
def validate_attr_rgb(obj, attr_name, value, accept_single_num=False):

    if accept_single_num and isinstance(value, int) and 0 <= value < 2**24:
        return (int(np.floor(value / 2 ** 16)), int(np.floor(value / 256)) % 256, value % 256)

    validate_attr_type(obj, attr_name, value, tuple, type_name="(red,green,blue)")
    if len(value) != 3 or \
            not isinstance(value[0], int) or not (0 <= value[0] < 256) or \
            not isinstance(value[1], int) or not (0 <= value[1] < 256) or \
            not isinstance(value[2], int) or not (0 <= value[2] < 256):
        raise TypeError("trajtracker error: {:}.{:} was set to an invalid value ({:}) - expecting (red,green,blue)".format(_get_type_name(obj), attr_name, value))

    return value

#--------------------------------------
def validate_attr_is_coord(obj, attr_name, value, change_none_to_0=False):

    if value is None and change_none_to_0:
        return (0, 0)

    if isinstance(value, geometry.XYPoint):
        value = (value.x, value.y)

    validate_attr_anylist(obj, attr_name, value, 2, 2)
    validate_attr_type(obj, "{:}[0]".format(attr_name), value[0], int)
    validate_attr_type(obj, "{:}[1]".format(attr_name), value[1], int)

    return value

#--------------------------------------
def validate_attr_numeric(obj, attr_name, value, none_value=NoneValues.Invalid):
    if value is None:
        if none_value == NoneValues.Invalid:
            raise TypeError(ErrMsg.attr_invalid_type(_get_type_name(obj), attr_name, "numeric", "None"))
        elif none_value == NoneValues.Valid:
            pass
        elif none_value == NoneValues.ChangeTo0:
            value = 0

    if value is not None and not isinstance(value, numbers.Number):
        raise TypeError(ErrMsg.attr_invalid_type(_get_type_name(obj), attr_name, "numeric", value))

    return value

#--------------------------------------
def validate_attr_not_negative(obj, attr_name, value):
    if value is not None and value < 0:
        msg = "trajtracker error: {0}.{1} was set to a negative value ({2})".format(_get_type_name(obj), attr_name, value)
        raise ValueError(msg)

#--------------------------------------
def validate_attr_positive(obj, attr_name, value):
    if value is not None and value <= 0:
        msg = "trajtracker error: {0}.{1} was set to a negative/0 value ({2})".format(_get_type_name(obj), attr_name, value)
        raise ValueError(msg)

#============================================================================
#   Validate function arguments
#============================================================================

#-------------------------------------------------------------------------
def validate_func_arg_type(obj, func_name, arg_name, value, arg_type, none_allowed=False, type_name=None):

    if (value is None and not none_allowed) or (value is not None and not isinstance(value, arg_type)):
        if type_name is None:
            type_name = _get_type_name(arg_type)

        raise TypeError("trajtracker error: {:}() was called with a non-{:} {:} ({:})".format(
            _get_func_name(obj, func_name), type_name, arg_name, value))

#--------------------------------------
def validate_func_arg_not_negative(obj, func_name, arg_name, value):

    if value is not None and value < 0:
        raise ValueError("trajtracker error: Argument '{:}' of {:}() has a negative value ({:})".format(arg_name, _get_func_name(obj, func_name), value))

#--------------------------------------
def validate_func_arg_anylist(obj, func_name, arg_name, value, min_length=None, max_length=None, none_allowed=False):

    if value is None and none_allowed:
        value = ()

    validate_func_arg_type(obj, func_name, arg_name, value, (list, tuple, np.ndarray), type_name="list/tuple")
    if min_length is not None and len(value) < min_length:
        raise TypeError("trajtracker error: Argument {:} of {:}() cannot be set to a collection with {:} elements - a minimal of {:} elements are expected".
                         format(arg_name, _get_func_name(obj, func_name), len(value), min_length))
    if max_length is not None and len(value) > max_length:
        raise TypeError("trajtracker error: Argument {:} of {:}() cannot be set to a collection with {:} elements - a maximum of {:} elements is allowed".
                         format(arg_name, _get_func_name(obj, func_name), len(value), max_length))

    return value

#--------------------------------------
def validate_func_arg_positive(obj, func_name, arg_name, value):
    if value is not None and value <= 0:
        raise ValueError("trajtracker error: Argument {:} of {:}() has a negative/0 value ({:})".format(arg_name, _get_func_name(obj, func_name), value))

#--------------------------------------
def _get_func_name(obj, func_name):
    if obj is None:
        return func_name
    else:
        return "{:}.{:}".format(_get_type_name(obj), func_name)


import numpy as np
np.random.seed(1337)  # for reproducibility
from keras.models import Model
from keras.layers import Dense, Input
import pandas as pd

def demo():
    # 数据预处理
    train_dataframe = pd.read_csv('./data/iris.data', header=0)
    train_dataset = train_dataframe.values
    total_count = 150
    train_level = int(total_count*0.7)

    x_train = train_dataset[0:train_level, 0:-1].astype('float')
    x_test = train_dataset[train_level:, 0:-1].astype('float')
    x_train = x_train.reshape((len(x_train), np.prod(x_train.shape[1:])))
    x_test = x_test.reshape((len(x_test), np.prod(x_test.shape[1:])))
    print(x_train.shape)
    print(x_test.shape)

    # 压缩特征维度至5维
    encoding_dim = 2
    # this is our input placeholder
    data_input = Input(shape=(4,), name="data_input")
    decoder_input = Input(shape=(encoding_dim,), name="decoder_input")

    # 编码层
    encoded_1 = Dense(128, activation='relu', name='encoded_1')(data_input)
    encoded_2 = Dense(64, activation='relu', name='encoded_2')(encoded_1)
    encoded_3 = Dense(10, activation='relu', name='encoded_3')(encoded_2)
    encoded_4 = Dense(encoding_dim, name='encoded_4')(encoded_3)

    # 解码层
    decoded_1 = Dense(10, activation='relu', name='decode_1')(encoded_4)
    decoded_2 = Dense(64, activation='relu', name='decoded_2')(decoded_1)
    decoded_3 = Dense(128, activation='relu', name='decoded_3')(decoded_2)
    decoded_4 = Dense(4, name='decoded_4')(decoded_3)

    # 构建自编码模型
    autoencoder = Model(inputs=data_input, outputs=decoded_4)

    # 构建编码模型
    encoder = Model(inputs=data_input, outputs=encoded_4)

    # 构建解码模型
    _decoded_1 = autoencoder.get_layer(name='decode_1')(decoder_input)
    _decoded_2 = autoencoder.get_layer(name='decoded_2')(_decoded_1)
    _decoded_3 = autoencoder.get_layer(name='decoded_3')(_decoded_2)
    _decoded_4 = autoencoder.get_layer(name='decoded_4')(_decoded_3)
    decoder = Model(inputs=decoder_input, outputs=_decoded_4)

    # compile autoencoder
    autoencoder.compile(optimizer='adam', loss='mse')

    # training
    autoencoder.fit(x_train, x_train, epochs=100, batch_size=10, shuffle=True)

    encoded_iris = encoder.predict(x_test)
    print(encoded_iris)

    decoded_iris = decoder.predict(encoded_iris)
    print(decoded_iris)

    autoencoder_img = autoencoder.predict(x_test)
    print(autoencoder_img)

if __name__ == '__main__':
    demo()


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

#constant
global a, b, checkDotsNum
a,b = np.array([-1, 1])+0.2
checkDotsNum = 100

#test function
def f(x):
    try:
        #return x**2 - np.sin(10*x)
        #return np.sin(x)+np.cos(x)
        #return x**3 - np.exp(x) + 1
        #return np.cos(x)/np.sin(x) - x
        return x**2 - np.arcsin(x-0.2)
    except:
        print("ha" , x)
#Init
def Init1(n):
    xData = np.linspace(a,b,n)
    yData = f(xData)
    return xData, yData

#Chebyshev Init
def Init2(n):
    ChebDots = lambda i: 0.5*((b-a)*np.cos(np.pi*(2*i+1)/(2*(n+1)))+b+a)
    preData = np.linspace(0,n,n)
    xData = ChebDots(preData)
    yData = f(xData)
    return xData, yData

#Lagrange Method
def Lagr(x, f, n, par=None):
    if par == None:
        xData, yData = Init1(n)
    if par == 1:
        xData, yData = Init2(n)
    result = 0
    for i in range (0, len(xData)):
        curDot = xData[i]
        coef = np.linspace(1,1,len(x))
        for j in range (0, len(xData)):
            if (i != j):
                coef *= (x-xData[j])/(curDot-xData[j])
        result += f(curDot)*coef

    return result

#Newton metgod
def New(x,f,n, par=None):
    if par == None:
        xData, yData = Init1(n)
    if par == 1:
        xData, yData = Init2(n)
    result = 0
    for i in range (0, len(xData)):
        coef = 1
        for j in range(0, i):
            coef *= x-xData[j]

        dd = 0
        for j in range(0, i+1):
            g = 1
            for k in range(0, i+1):
                if k != j:
                    g *= 1/(xData[j]-xData[k])
            dd += yData[j]*g
        result += coef*dd

    return result

#init
x = np.linspace(a,b,checkDotsNum)
n = 15
y = f(x)
yL = Lagr(x, f, n)
yN = New(x, f, n)
yLCh = Lagr(x, f, n, 1)
yNCh = New(x, f, n, 1)

fig, ax = plt.subplots()
ax.plot(x,y, 'k', label = 'test function', linewidth=1.5)
#ax.plot(x,yL, 'r', label = 'Lagrange polynomial', linewidth=1.5)
ax.plot(x,yN, 'b', label = 'Newton polynomial', linewidth=1.5)
#ax.plot(x,yLCh, 'm', label = 'Lagrange polynomial Chebyshev', linewidth=1.5)
ax.plot(x,yNCh, 'c', label = 'Newton polynomial Chebyshev', linewidth=1.5)
ax.legend(loc='upper center', shadow=True, fontsize=15)
fig.set_size_inches(12, 10)

RLagr = {}
RNew = {}
RLagrCh = {}
RNewCh = {}
start = 2
finish = 42
step = 2

#computing digression
y = f(x)
for i in range(start,finish,step):
    yL = Lagr(x, f, i)
    yN = New(x, f, i)
    yLCh = Lagr(x, f, i, 1)
    yNCh = New(x, f, i, 1)
    RLagr[i] = max(abs(y-yL))
    RNew[i] = max(abs(y-yN))
    RLagrCh[i] = max(abs(y-yLCh))
    RNewCh[i] = max(abs(y-yNCh))

#plots digression
fig1, ax1 = plt.subplots()
ax1.plot(RLagr.keys(),RLagr.values(), label = 'Lagrange digression ', linewidth=2)
ax1.plot(RNew.keys(),RNew.values(), '-.', label = 'Newton digression ', linewidth=2)
ax1.plot(RLagrCh.keys(),RLagrCh.values(), label = 'Lagrange-Chebyshev digression ', linewidth=2)
ax1.plot(RNewCh.keys(),RNewCh.values(),'-.', label = 'Newton-Chebyshev digression ', linewidth=2)
ax1.legend(loc='upper center', shadow=True, fontsize=15)
fig1.set_size_inches(12, 10)

#export to table
s="number of nodes---number of checking dots---Lagrange digression---Newton digression"
for i in range(start,finish,step):
    s += "\n" + str(i) + "---" + str(checkDotsNum) + "---" + str(RLagr[i]) + "---" + str(RNew[i])

table=['<htm>
']
for line in s.splitlines():
    if not line.strip():
        continue
    table.append(r'
{}	{}	{}	{}
'.format(*line.split('---')))

table.append('
')
html_str = ''.join(table)
f = open("yourpage.html","w")
f.write(html_str)
f.close()


import configparser
import os.path
import shutil
import subprocess
from .verbosity import Verbosity

class ArgumentException(BaseException):
    pass

class Command(object):

    def __init__(self, argparse, cmd_name, cmd_help, require_ini_file=True):
        self.__require_ini_file = require_ini_file
        self.__ini_dict = {}
        self.__argparse = argparse.add_parser(cmd_name, help=cmd_help)
        if self.__require_ini_file:
            self.__argparse.add_argument('inifile', help="path to INI file with configuration definitions")
        self.__argparse.set_defaults(CmdObject=self)
        self.__args = None

    def getGeneralArg(self, arg):
        return self.__ini_dict["GENERAL"][arg]

    def add_argument(self, *args, **kwargs):
        # forward to argparser
        self.__argparse.add_argument(*args, **kwargs)

    def cleanDir(self, dir_path):
        shutil.rmtree(dir_path)
        self.mkdirs(dir_path)

    def parseArgs(self, args):
        self.__args = args

        if self.__require_ini_file:
            cp = configparser.ConfigParser()
            cp.read(self.__args.inifile)
            self.__ini_dict = cp

    def getArg(self, arg_name):
        arg_name = arg_name.replace("-", "_")
        return getattr(self.__args, arg_name)

    def getIniSection(self, section_name):
        if section_name in self.__ini_dict:
            return self.__ini_dict[section_name]
        else:
            return None

    def process(self):
        raise NotImplementedError("You must subclass the Command class and overload the process() method!")

    def mkdirs(self, dirs):
        """
            Create complete directory path.
            No error is raised if path already existent.
        """
        if not os.path.isdir(dirs):
            os.makedirs(dirs)

    def copytree(self, src, dst):
        """
            Copies a source directory to a destination directory,
            including all subdirectories and files
        """

        # ignore if src and dst are equal
        src = os.path.abspath(src)
        dst = os.path.abspath(dst)
        if src == dst:
            return

        if not os.path.isdir(src):
            raise ValueError("Source path must be a directory: " + str(src))
        if not os.path.isdir(dst):
            self.mkdirs(dst)

        for entry in os.listdir(src):
            entry_src = os.path.join(src, entry)
            entry_dst = os.path.join(dst, entry)

            if os.path.isdir(entry_src):
                self.copytree(entry_src, entry_dst)
            elif os.path.isfile(entry_src):
                # shutil.copy(entry_src, entry_dst)  # <- somehow shutil.copy does cause issues with permissions
                subprocess.run(['cp', entry_src, entry_dst], check=True)  # cp command works best


### juego.py
### Procedimiento de control de un juego.
###===================================================================

from minimax import *

###*******************************************************************
### Funciones y variables externas
###*******************************************************************

### Procedentes de la clase Juego:
### estado_inicial
###    => estado inicial del juego.
### es_estado_final(ESTADO)
###    => True, si  ESTADO es final; False en caso contrario.
### es_estado_ganador(ESTADO, TURNO, JUGADOR)
###    => True, si y sólo si en el ESTADO, cuando le toca mover al
###       jugador TURNO, el JUGADOR ha ganado la partida.
### movimientos(ESTADO)
###    => Lista con las representaciones de los movimientos aplicables
###       al ESTADO.
### aplica(MOVIMIENTO, ESTADO)
###    => Aplica el MOVIMIENTO al ESTADO para generar un nuevo estado.

###*******************************************************************
### § Procedimientos de control de juegos.
###*******************************************************************

### Los nodos del árbol, NODO_J, de desarrollo del juego serán
### diccionarios con 3 campos: ESTADO, JUGADOR y VALOR.

### ESTADO describirá la situación del juego, JUGADOR valdrá MAX, si
###   le toca jugar al ordenador, o MIN, si le toca jugar al humano, y
###   VALOR almacenará el valor de la situación del juego.

### crea_nodo_j_inicial(JUEGO, JUGADOR)
### Valor: El NODO_J asociado al estado_inicial del juego, en el que
###   el JUGADOR comienza la partida.

def crea_nodo_j_inicial (juego, jugador):
    return {'estado' : juego.estado_inicial, 'jugador' : jugador}

### escribe_nodo_j(NODO_J)
### Efecto: Escribe en pantalla los campos ESTADO y JUGADOR del NODO_J.

def escribe_nodo_j (juego, nodo_j):
  print('Estado  : {0}\nJugador : {1}'.format(juego.str_estado(nodo_j['estado']),
                                              nodo_j['jugador']))

### control(JUEGO, JUGADOR_INICIAL, PROCEDIMIENTO)
### Efecto: Controla el desarrollo de un juego.
### Procedimiento:
### 1. crear el nodo de juego inicial con JUGADOR_INICIAL como jugador
###    que comienza la partida.
### 2. Si el estado_inicial del JUEGO es un estado final,
###    2.1 analizar el final para el nodo de juego inicial
###    2.2 en caso contrario,
###        2.2.1 Si el JUGADOR_INICIAL es MAX,
###              2.2.1.1 procesar la jugada de la máquina.
###              2.2.1.2 en caso contrario, procesar la jugada del
###                      humano.

def control(juego, jugador_inicial, procedimiento = [minimax, 5]):
  nodo_j_inicial = crea_nodo_j_inicial(juego, jugador_inicial)
  if juego.es_estado_final(juego.estado_inicial):
    analiza_final(juego, nodo_j_inicial)
  else:
    if jugador_inicial == 'MAX':
      jugada_maquina(juego, procedimiento, nodo_j_inicial)
    else:
      jugada_humana(juego, procedimiento, nodo_j_inicial)

### analiza_final(JUEGO, NODO_J)
### Efecto: Escribe en pantalla el NODO_J y si gana la máquina,
###   escribe en pantalla "La maquina ha ganado", si gana el humano,
###   escribe en pantalla "El humano ha ganado", en caso contrario
###   escribe en pantalla "Empate".

def analiza_final(juego, nodo_j):
  escribe_nodo_j(juego, nodo_j)
  if juego.es_estado_ganador(nodo_j['estado'], nodo_j['jugador'], 'MAX'):
     print('La maquina ha ganado')
  elif juego.es_estado_ganador(nodo_j['estado'], nodo_j['jugador'], 'MIN'):
    print('El humano ha ganado')
  else:
    print('Empate')

### escribe_movimientos(movimientos)
### Efecto: Escribe en pantalla la lista de los movimientos

def escribe_movimientos(juego, movimientos):
    print('Los movimientos permitidos son:')
    numero = 0
    for m in movimientos:
        print('      {0} ({1})'.format(juego.str_movimiento(m), numero))
        numero += 1

### jugada_humana(JUEGO, PROCEDIMIENTO, NODO_J)
### Efecto: Procesa la jugada humana.
### Procedimiento:
### 1. Escribe en pantalla el NODO_J
### 2. Escribe en pantalla la lista de los movimientos posibles
### 3. Solicita del jugador humano una jugada, se trata de un número que
###    representa el movimiento que el humano quiere hacer.
### 4. Si el dato introducido por el jugador humano es un número que se
###    corresponde con una posición en la lista de movimientos posibles, hacer:
###    4.1.1 Aplicar el movimiento elegido al estado del NODO_J, creando un
###          NUEVO_ESTADO.
###          4.1.2.1.1 Crear el nodo SIGUIENTE con el NUEVO_ESTADO y en el que
###                    el jugador es MAX.
###          4.1.2.1.2 Si el NUEVO_ESTADO es un estado final,
###                    4.1.2.1.2.1 analizar el nodo final
###                    4.1.2.1.2.2 en caso contrario, procesar la jugada de la
###                                máquina.
###    4.2 en caso contrario hacer,
###        4.2.1 Escribir en pantalla que la elección es incorrecta.
###        4.2.2 Procesar la jugada del humano.

def jugada_humana(juego, procedimiento, nodo_j):
  escribe_nodo_j(juego, nodo_j)
  movimientos_posibles = juego.movimientos(nodo_j['estado'])
  escribe_movimientos(juego, movimientos_posibles)
  m = int(input('Tu turno: '))
  if (-1 < m <  len(movimientos_posibles)):
    nuevo_estado = juego.aplica(movimientos_posibles[m], nodo_j['estado'])
    siguiente = {'estado' : nuevo_estado, 'jugador' : 'MAX'}
    if juego.es_estado_final(nuevo_estado):
      analiza_final(juego, siguiente)
    else:
      jugada_maquina(juego, procedimiento, siguiente)
  else:
    print('  {} es ilegal.'.format(m))
    jugada_humana(juego, procedimiento, nodo_j)

### jugada_maquina(JUEGO, PROCEDIMIENTO, NODO_J)
### Efecto: Procesa la jugada de la máquina.
### Procedimiento:
### 1. Escribe en pantalla el NODO_J
### 2. Aplica el PROCEDIMIENTO de decisión al NODO_J y determina el nodo
###    SIGUIENTE
### 3. Si el estado del nodo SIGUIENTE es un estado final,
###    3.1 analizar el nodo final SIGUIENTE
###    3.2 en caso contrario, procesar la jugada humana.

def jugada_maquina(juego, procedimiento, nodo_j):
  escribe_nodo_j(juego, nodo_j)
  print('Mi turno.')
  movimiento, estado = aplica_decision(juego, procedimiento, nodo_j)
  if juego.es_estado_final(estado):
    analiza_final(juego, {'estado': estado, 'jugador': 'MIN'})
  else:
    jugada_humana(juego, procedimiento, {'estado': estado, 'jugador': 'MIN'})

def aplica_decision(juego, procedimiento, nodo_j):
  return procedimiento[0](juego, nodo_j['estado'], procedimiento[1])


def test_adapters(input):
    input = sorted(input)
    diffs = {
        1: 0,
        2: 0,
        3: 1
    }
    actual_adapter = 0
    for adapter in input:
        diffs[adapter-actual_adapter] += 1
        actual_adapter = adapter
    return diffs[1]*diffs[3]

if __name__ == '__main__':
    with open('input.txt', 'r') as f:
        input = f.read()
    input = input.splitlines()
    input = [int(i) for i in input]
    print(test_adapters(input))


W = int(input())
N,K = map(int,input().split())

A = []
B = []
for i in range(N):
  a,b = map(int,input().split())
  A.append(a)
  B.append(b)

#dp[i][k][w]:=i番目までのスクショでk枚使って合計幅がwでの重要度の最大値
dp=[[0]*(W+1) for _ in range(K+1)]
for i in range(N):
    print('----')
    for k in range(K,0,-1):
        for w in range(W, 0, -1):
            if 0<=w-A[i]:
                dp[k][w]=max(dp[k][w], dp[k-1][w-A[i]]+B[i])
        print(dp[0])
        print(dp[1])
        print(dp[2])
        print(dp[3])


"""copy of custom_functions.py from DDDAS_2D_highway, branch 3d_xyt"""

import numpy as np
import math
from scipy import integrate
import random
import os
from scipy import interpolate
from scipy.optimize import fsolve
import pickle
import csv
from definition import c_r2

Pi =math.pi

def permute_Y(xs, ys):
    P = np.zeros((len(ys), len(xs)))
    j = len(xs)
    for i in range(len(ys)):
        j = j - 1
        P[i, j] = 1
    return P

def my_meshgrid(x, y):
    x = list(x)
    xm = []
    for i in range(len(x)):
        xm.append(x)
    xm = np.asarray(xm)

    y = list(y)
    y.reverse()
    ym = []
    for i in range(len(y)):
        ym.append(y)
    ym = np.asarray(ym)

    return xm, ym.T

def get_angle_in_0_2pi(angle):
    return (angle + 2 * np.pi) % (2 * np.pi)

def calculate_reward_const_dt(dt, xs, ys, so, sn, vnet_x, vnet_y, a, degree = False):

    if (so[1] == sn[1] and so[2] == sn[2]):
        dt_new = dt
    else:
        ni = len(ys)

        io = so[1]
        jo = so[2]
        xo = xs[jo]
        yo = ys[ni - 1 - io]

        inw = sn[1]
        jnw = sn[2]
        xnw = xs[jnw]
        ynw = ys[ni - 1 - inw]
        conv_factor=1
        if degree==True:
            conv_factor=11000
        h = conv_factor*( ((xnw - xo) ** 2 + (ynw - yo) ** 2) ** 0.5 )

        r1 = h/((vnet_x ** 2 + vnet_y ** 2) ** 0.5)

        theta1 = get_angle_in_0_2pi(math.atan2(vnet_y, vnet_x))
        theta2 = get_angle_in_0_2pi(math.atan2(ynw- yo, xnw -xo))
        # print("thetas = ",theta1, theta2)
        theta = np.abs(theta1 - theta2)

        r2 = c_r2*np.abs(math.sin(theta))
        dt_new = r1 + r2
        # print("r1= ", r1, "r2= ", r2)
    return -dt_new

def get_minus_dt(dt):
    return -dt

def calculate_reward_var_dt(dt, xs, ys, so, sn, xp, yp, Vx, Vy):
    # if (Vx == 0 and Vy == 0) or (so == sn):
    if (so[1] == sn[1] and so[2] == sn[2]):
        dt_new = dt
    else:
        ni = len(ys)

        io = so[1]
        jo = so[2]
        xo = xs[jo]
        yo = ys[ni - 1 - io]

        inw = sn[1]
        jnw = sn[2]
        xnw = xs[jnw]
        ynw = ys[ni - 1 - inw]

        # print((xo, yo), (xp, yp), (xnw, ynw))
        A = B = C = 0
        # distance of sn (new state) from line
        if xnw - xo == 0:
            d = xp - xnw
        else:
            # line Ax+ By + C =0 line along Vnet
            A = (yp - yo) / (xp - xo)
            B = -1
            C = yo - (xo * (yp - yo) / (xp - xo))

            d = (A * xnw + B * ynw + C) / (A ** 2 + B ** 2) ** 0.5

        # distance from so to sn
        h = ((xnw - xo) ** 2 + (ynw - yo) ** 2) ** 0.5

        # print("d", d, "h", h)

        # length of tangent

        tan_len = (h ** 2 - d ** 2) ** 0.5
        if h ** 2 < d ** 2:
            print("----------------------BUG HAI ------------------------------")
            print("so,sn=", so, sn)
            print("(xo,yo)=", (xo, yo))
            print("(xnw,ynw)=", (xnw, ynw))
            print("(xp,yp=", (xp, yp))
            print("A, B, C =", A, B, C)
            print("h=", h)
            print("d=", d)
            print("tan_len=", tan_len)
        # actual distance travelled in dT
        tot_dis = ((xp - xo) ** 2 + (yp - yo) ** 2) ** 0.5
        # print("tan_len=", tan_len, "tot_dis", tot_dis)

        err = tot_dis - tan_len
        # print(err)

        dt_new = dt - (err / ((Vx ** 2 + Vy ** 2) ** 0.5))

    return -dt_new

"""

The functions below are used in the stochatic version of the DP
Problem

"""

# state transition probability derived from prob dist of velocities
def p_sas(xi, xf, yi, yf, sigx, sigy):
    def pdf(x, y):
        ux = 0
        uy = 0
        return np.exp(- ((((x - ux) ** 2) / (2 * (sigx ** 2))) + (((y - uy) ** 2) / (2 * (sigy ** 2))))) / (
                2 * math.pi * sigx * sigy)

    return integrate.nquad(pdf, [[xi, xf], [yi, yf]])[0]

# generates matrix with samples from normal curve. Used to simulate uncertainty in velocity field
def gaussian_matrix(t, r, c, u, sigma):
    a = np.zeros((t, r, c))
    for k in range(t):
        for i in range(r):
            for j in range(c):
                a[k, i, j] = np.random.normal(u, sigma)
    return a

# finds number of states s' on either sides where p_sas is >thresh , i.e. significant
def find_mn(dx, dy, sigx, sigy, thresh):
    i = 0
    j = 0
    val = 1
    while val > thresh:
        val = p_sas((j - 0.5) * dx, (j + 0.5) * dx, (i - 0.5) * dy, (i + 0.5) * dy, sigx, sigy)
        j = j + 1
    m = j - 1

    val = 1
    i = 0
    j = 0
    while val > thresh:
        val = p_sas((j - 0.5) * dx, (j + 0.5) * dx, (i - 0.5) * dy, (i + 0.5) * dy, sigx, sigy)
        i = i + 1
    n = i - 1
    return m, n

def transition_probs(m, n, dx, dy, sigx, sigy, thresh):
    psas_dict = {}
    for i in range(-n, n + 1, 1):
        for j in range(-m, m + 1, 1):
            prob = p_sas((j - 0.5) * dx, (j + 0.5) * dx, (i - 0.5) * dy, (i + 0.5) * dy, sigx, sigy)
            if prob > thresh:
                psas_dict[(i, j)] = prob
    return psas_dict, psas_dict.keys()

def stoch_vel_field(d_vStream, xm, ym, cov_sigma, coef):
    t, r, c = d_vStream.shape
    st_vStream=np.zeros((t,r,c))
    fxgrd=np.ndarray.flatten(xm)
    fygrd=np.ndarray.flatten((ym))
    for k in range(t):
        fl_vel=np.ndarray.flatten(d_vStream[k,:,:])
        l=len(fl_vel)
        cov=np.zeros((l,l))
        for i in range(l):
            for j in range(l):
                rsqm=(fxgrd[i]-fxgrd[j])**2 + (fygrd[i]-fygrd[j])**2
                cov[i,j]=coef*np.exp(-rsqm/(2*cov_sigma**2))
        fl_st_vel=np.random.multivariate_normal(fl_vel,cov)
        st_vStream[k,:,:]=fl_st_vel.reshape((r,c))
    return st_vStream

def boltzman_stoch_action(Q,s,g,T):
    prob={}
    sum_of_probs=0
    for a in g.actions:
        sum_of_probs += math.exp(Q[s][a]/T)
    for a in g.actions:
        prob[a]=(math.exp(Q[s][a]/T))/sum_of_probs

    #generate intervals over (0,1) for actions
    intervals={}
    i=0
    first=True
    a_old=None
    for a in g.actions:
        if first:
            first=False
            intervals[a]=(0,prob[a])
        else:
            intervals[a] = (prob[a_old], prob[a] + prob[a_old])
        a_old = a

    #checks if a given value is in the range (a,b)
    def check_if_in_range(value, Range):
        if value>=Range[0] and value<=Range[1]:
            return True

    #sample action from prob distribution
    rand_num=np.random.random()
    for action, interval_range in intervals:
        if check_if_in_range(rand_num, interval_range):
            return action

def stochastic_action_eps_greedy(policy, s, g, eps, Q=None):
    p = np.random.random()
    n = len(g.actions)
    if p < (1 - eps):
        if Q==None:
            newa = policy[s]
        else:
            newa, _ = max_dict(Q[s])
    else:
        #returns a random integer between [0,n-1]
        i = random.randint(0, n - 1)
        newa = g.actions[i]
    return newa

def random_action(a, s, g, eps):
    p = np.random.random()
    n = len(g.actions)
    if p < (1 - eps + (eps / n)):
        newa = a
    else:
        i = random.randint(0, n - 1)
        newa = g.actions[s][i]

    return newa

def initialise_directed_policy(g, action_states):
    policy = {}

    Pi = math.pi
    for s in action_states:
        i, j = s
        # print("start", s)
        i2, j2 = g.endpos
        # print("i2,j2", i2, j2)
        if j2 == j:
            if i2 > i:
                policy[s] = (1, 1.5 * Pi)
            elif i2 < i:
                policy[s] = (1, 0.5 * Pi)
        elif j2 > j:
            if i2 > i:
                policy[s] = (1, 1.75 * Pi)
            elif i2 < i:
                policy[s] = (1, 0.25 * Pi)
            elif i2 == i:
                policy[s] = (1, 0)
        elif j2 < j:
            if i2 > i:
                policy[s] = (1, 1.25 * Pi)
            elif i2 < i:
                policy[s] = (1, 0.75 * Pi)
            elif i2 == i:
                policy[s] = (1, Pi)
        # if i == 9 or j == 9:
        #     print("state, action ", s, policy[s])

    return policy

def initialise_policy(g):
    policy = {}
    n=len(g.actions)
    for s in g.state_space():
        policy[s]=None

    for s in g.ac_state_space():
        i = random.randint(0, n - 1)
        policy[s] = g.actions[i]

    return policy

def initialise_policy_from_initQ(Q):
    policy={}
    for s in Q.keys():
        for a in Q[s].keys():
            besta,_=max_dict(Q[s])
            policy[s]=besta
    return policy

def initialise_Q_N(g, init_Qval, init_Nval):
    Q = {}
    N = {}
    for s in g.ac_state_space():
        Q[s] = {}
        N[s] = {}
        for a in g.actions:
            Q[s][a] = init_Qval
            N[s][a] = init_Nval
    return Q, N

def calc_net_velocity_angle(vx,vy,a):
    F, theta = a
    return get_angle_in_0_2pi( math.atan2(F*math.sin(theta) + vy, F*math.cos(theta) + vx) )

def calc_net_velocity(vx, vy, a):
    F, theta = a
    vy_net = F*math.sin(theta) + vy
    vx_net = F*math.cos(theta) + vx
    mag_v = (vx_net**2 + vy_net**2)**.5
    ang_v = get_angle_in_0_2pi(math.atan2(vy_net, vx_net))
    return (mag_v, ang_v)

def action_angle(traj_theta, actions, vx, vy, F):
    diff_list = []
    blocked_actions = []
    angle_list = []
    for idx in range(len(actions)):
        angle_list.append(actions[idx][1])
        (net_v_mag, net_v_angle) = calc_net_velocity(vx, vy, actions[idx])
        if net_v_mag < 0.001:
            blocked_actions.append(idx)
        diff_list.append(np.abs(traj_theta - net_v_angle))
    sorted_ids = np.argsort(diff_list)

    min_id = None
    for idx in sorted_ids:
        if idx in blocked_actions:
            pass
        else:
            min_id = idx
            # print("min_id =", min_id)
            break
    action = actions[min_id]
    return action

# def Calculate_action(state_1,p1,p2, vx, vy, g):
#     traj_theta = get_angle_in_0_2pi(math.atan2(p2[1] - p1[1], p2[0] - p1[0]))
#     F = g.actions[0][0]
#     action = action_angle(traj_theta, g.actions, vx, vy, F)
#     return action
def Calculate_action(state_1, state_2, p1, p2, vx, vy, g, coord_traj_theta = False):
    #coord_traj_theta
    if coord_traj_theta == True:
        traj_theta = get_angle_in_0_2pi(math.atan2(p2[2] - p1[2], p2[1] - p1[1]))
    # state_traj_theta
    else:
        t1, i1, j1 = state_1
        t2, i2, j2 = state_2

        p_s1 = (t1, g.xs[j1], g.ys[g.ni - 1 - i1])
        p_s2 = (t2, g.xs[j2], g.ys[g.ni - 1 - i2])
        traj_theta = get_angle_in_0_2pi(math.atan2(p2[2] - p1[2], p2[1] - p1[1]))
    F = g.actions[0][0]
    action = action_angle(traj_theta, g.actions, vx, vy, F)
    return action

def initialise_guided_Q_N(g, init_Qval, guiding_Qval,  init_Nval):
    Q = {}
    N = {}
    end_i, end_j = g.endpos
    # p2 = (None, g.xs[end_j], g.ys[g.ni - 1 - end_i])
    #take p2 to be the end point, in order to get action that leads to the end point
    p2 = (None, g.xs[end_j], g.ys[g.ni - 1 - end_i])
    #Here vx and vys are initialised to zero. this will just make
    # the action heading (not net movement direction) towards endpoint
    Vx = Vy = np.zeros((len(g.xs), len(g.ys)))

    s_dummy = None
    for s in g.ac_state_space():
        Q[s] = {}
        N[s] = {}
        g.set_state(s)
        p1 = (None, g.x, g.y)
        # p1 = (g.x, g.y)
        t, m, n= s
        # targeting_action = Calculate_action(s, p1, p2, Vx[m,n], Vy[m,n],  g)
        targeting_action = Calculate_action(s, s_dummy, p1, p2, Vx[m,n], Vy[m,n],  g, coord_traj_theta = True)

        for a in g.actions:

            if a==targeting_action:
                Q[s][a] = guiding_Qval

            else:
                Q[s][a] = init_Qval

            N[s][a] = init_Nval

    return Q, N

def max_dict(d):
    # returns the argmax (key) and max (value) from a dictionary
    # put this into a function since we are using it so often
    max_key = None
    max_val = float('-inf')
    for k, v in d.items():
        # print("dict test:", k , v)
        if v > max_val:
            max_val = v
            max_key = k
    return max_key, max_val

def writePolicytoFile(policy, filename):
    outputfile = open(filename+'.txt', 'w')
    print(policy, file=outputfile)
    outputfile.close()
    return

def picklePolicy(policy, filename):
    with open(filename +'.p', 'wb') as fp:
        pickle.dump(policy, fp, protocol=pickle.HIGHEST_PROTOCOL)

def read_pickled_File(filename):
    with open(filename +'.p', 'rb') as fp:
        File = pickle.load(fp)
    print("READING " + filename + '.p')
    return File

def createFolder(directory):
    try:
        if not os.path.exists(directory):
            os.makedirs(directory)
    except OSError:
        print('Error: Creating directory. ' + directory)

def Map_vector_to_grid(u, node_u):
    m, n = node_u.shape
    U = np.zeros((m - 2, n - 2))
    for i in range(1, m - 1):
        for j in range(1, n - 1):
            matlab_ind = node_u[i, j]
            python_ind = matlab_ind - 1
            U[i - 1, j - 1] = u[python_ind, 0]

    return U

# Interpolation of velocites from their grids to XP,YP grid
def interpolate_to_XP_grid(XU, YU, U, XP, YP):
    flat_xu = np.ndarray.flatten(XU)
    flat_yu = np.ndarray.flatten(YU)
    flat_u = np.ndarray.flatten(U)
    U_interpolated = interpolate.griddata((flat_xu, flat_yu), flat_u, (XP, YP))
    return U_interpolated

def append_summary_to_summaryFile(summary_file, summary_data):
    myFile = open(summary_file, 'a')
    with myFile:
       writer = csv.writer(myFile)
       writer.writerows([summary_data])

def read_n_rearrange_trajSet(filename):
    """
    Rearranges list to be usable in frechet_dist()
    :param filename: filename of pickled traj_set coordinates obtained from plot_all_traj_set()
    :return: rearranged traj_set coords
    """
    old_trajSet =read_pickled_File(filename)
    new_traj_list = []
    print("len(old_trajSet) =", len(old_trajSet))

    for i in range(len(old_trajSet)):
        print("i= ", i)
        P = old_trajSet[i]
        Pnew = []
        print("len(P[0])= ", len(P[0]))
        for j in range(len(P[0])):
            Pnew.append([P[0][j],P[1][j]])
        new_traj_list.append(Pnew)
    return new_traj_list

def calc_mean_and_std(scalar_list):
    """
    calulates mean, variance and None count of entries in given list.
    :param scalar_list: list of scalar and None elements
    :return: mean, std dev, good_cnt, Nonecount
    """

    cnt = 0
    sum_x = 0
    sum_x_sq = 0
    num_rzns = len(scalar_list)

    mean = 'a'
    std = 'a'
    none_cnt= 'a'

    for i in range(num_rzns):
        if scalar_list[i] != None:
            cnt += 1
            sum_x += scalar_list[i]
            sum_x_sq += scalar_list[i]**2

    if cnt == 0:
        print("\n $$$$------ ERROR: List contains only Nones --------$$$$ \n")

    try:
        mean = sum_x/cnt
        var = (sum_x_sq/cnt) - (sum_x/cnt)**2
        std = var**0.5
        none_cnt = num_rzns - cnt
    except:
        print("cnt = 0")

    return mean, std, cnt, none_cnt

def calc_mean_and_std_train_test(scalar_list,train_id_list, test_id_list):
    """
    calulates mean, variance and None count of entries in given list.
    :param scalar_list: ORDERED list of scalar and None elements.
            *_id_list: set containing test and train rzn ids
    :return: mean, std dev, good_cnt, Nonecount
    """

    cnt = [0, 0]
    sum_x = [0, 0]
    sum_x_sq = [0, 0]
    case_len =[len(train_id_list), len(test_id_list)]
    num_rzns = len(scalar_list)

    mean = ['a','a']
    var =['a', 'a']
    std = ['s','s']
    none_cnt = ['s', 's']
    none_cnt_perc = ['s', 's']

    for i in range(num_rzns): # this works because scalar_list is ordered from 0-5000
        if i in train_id_list:
            case = 0    # case 0 corresponds to train
        else:
            case = 1    # case 1 corresponds to test

        if scalar_list[i] != None:
            cnt[case] += 1
            sum_x[case] += scalar_list[i]
            sum_x_sq[case] += scalar_list[i]**2

    # if there are non0 test rzns but all lead to none, cnt[1]==0.
    if cnt[1] == 0 and case_len[1] != 0:
        print("\n $$$$------: List contains only Nones --------$$$$ \n")

    for case in range(2):
        try:
            if case_len[case]!=0:
                mean[case] = sum_x[case]/cnt[case]
                var[case] = (sum_x_sq[case]/cnt[case]) - (sum_x[case]/cnt[case])**2
                std[case] = var[case]**0.5
                none_cnt[case] = case_len[case] - cnt[case]
                none_cnt_perc[case] = none_cnt[case]/case_len[case]*100
        except:
            print("\n $$$$------ Raising excption: List contains only Nones --------$$$$ \n")

    return mean, std, cnt, none_cnt, none_cnt_perc

def get_list_of_rzns_without_lengthy_pde_paths(paths, target_num_rzns):
    """returns those rzn ids among 5k that DO NOT have pde paths longer than admisible by
        mdp formulation. We trajectories end at t=59.
        We currently remove top those rzns which may lead to t = 60 and then some random extra to get a round no.
        The same rzns will have to be used in DP
    """
    #get list of lengths for all 5k paths
    lenlist = []
    for k in range(5000):
        lenlist.append(len(paths[k,0]))
    len_array = np.array(lenlist)

    # only keep those rzns which have apt pde traj lenght
    count = 0
    goodlist = []
    for i in range(len(len_array)):
        length = len_array[i]
        if length <= 2380:
            #expected count = 3550 with 2360
            #expected count = 4028 with 2380
            count += 1
            goodlist.append(i)

    # remove extra rzns to round off to target_num_rzns
    len_goodlist = len(goodlist)
    diff = len_goodlist - target_num_rzns
    for i in range(diff):
        goodlist.pop()

    return goodlist

# def get_rzn_ids_for_training_and_testing(dt_size, target_num_rzns, paths):
#     """
#     target_num_rzns is the same as useful_num_rzns and is set up in setup_grid()
#     returns set of ids for training trajs and testing trajs by sm=ampling realisations from goodlist
#     input: traindata size, num of rzns (scalars)
#     """
#     random.seed(1)
#     goodlist = get_list_of_rzns_without_lengthy_pde_paths(paths, target_num_rzns)
#     id_list = random.sample(goodlist, target_num_rzns)
#     train_id_list = id_list[0:dt_size]
#     test_id_list = id_list[dt_size:target_num_rzns]
#     train_id_list.sort()
#     test_id_list.sort()
#     return train_id_list, test_id_list,  set(train_id_list), set(test_id_list), goodlist

# def get_rzn_ids_for_training_and_testing(dt_size, target_num_rzns, paths):
#     goodlist = [i for i in range(target_num_rzns)]
#     id_list = goodlist
#     train_id_list = id_list[0:5000]
#     test_id_list = id_list[4000:5000]
#     train_id_list.sort()
#     test_id_list.sort()
#     return train_id_list, test_id_list,  set(train_id_list), set(test_id_list), goodlist

# def get_rzn_ids_for_training_and_testing_v2(useful_num_rzns, dt_size):
#     id_list = [i for i in range(useful_num_rzns)] #[0..4999]
#     train_id_list = id_list[0:dt_size]
#     test_id_list = id_list[dt_size:useful_num_rzns]
#     return train_id_list, test_id_list,  set(train_id_list), set(test_id_list), goodlist

def get_rzn_ids_for_training_and_testing():
    goodlist = [i for i in range(5000)]
    id_list = goodlist
    train_id_list = goodlist
    test_id_list = id_list[4000:5000]

    return train_id_list, test_id_list,  set(train_id_list), set(test_id_list), goodlist

def print_sorted_Qs_kvs(g, Q, state):
    x = Q[state] #x is a dictionary of k: actions, v: action-values
    sorted_x = {k: v for k, v in sorted(x.items(), key=lambda item: item[1])}
    # print(sorted_x)
    print("Q[",state,"]:")
    for k in sorted_x:
        print(k, sorted_x[k])

    return sorted_x

def extract_velocity(vel_field_data, t, i, j, rzn):
    # all_u_mat, all_v_mat, all_ui_mat, all_vi_mat, all_Yi = vel_field_data
    #    0          1           2           3           4
    # vx = all_u_mat[t,i,j] + np.matmul(all_ui_mat[t, :, i,j], all_Yi[t, rzn,:])
    # vy = all_v_mat[t,i,j] + np.matmul(all_vi_mat[t, :, i,j], all_Yi[t, rzn,:])
    vx = vel_field_data[0][t, i, j] + np.matmul(vel_field_data[2][t, :, i, j],vel_field_data[4][t, rzn,:])
    vy = vel_field_data[1][t, i, j] + np.matmul(vel_field_data[3][t, :, i, j], vel_field_data[4][t, rzn,:])

    return vx,vy


from fastapi import FastAPI, File, UploadFile
import pytesseract
import cv2
import numpy as np
from requests.structures import CaseInsensitiveDict
from gyazo.api import Api
from gyazo.error import GyazoError
from gyazo.image import Image, ImageList
from time import sleep
from app.libs import trim
# os
import os
app = FastAPI()
client = Api(access_token=os.environ['GYAZO_ACCESS_TOKEN'])

@app.post("/upload/")
async def upload(file: UploadFile = File(...)):
    # cv2で画像を読み込み
    input_file = np.frombuffer(await file.read(), np.uint8)
    input_image = cv2.imdecode(input_file, cv2.IMREAD_COLOR)
    # グレースケールに変換
    gray_img = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY)

    # 適応的閾値処理
    binary_img = cv2.adaptiveThreshold(
        compressed_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 255, 2
    )
    # ガウシアンフィルタで画像の平滑化
    size = (3, 3)
    blur = cv2.GaussianBlur(binary_img, size, 0)
    # 大津の手法を使った画像の２値化
    _, th = cv2.threshold(blur, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    # # 白黒反転
    # th = cv2.bitwise_not(th)
    # # 大津の手法を使った画像の２値化
    # _, th = cv2.threshold(th, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
    # # 白黒反転で元に戻す
    # th = cv2.bitwise_not(th)

    # # サイズを500kbに圧縮
    image = compress_image_to_500kb(blur)
    # ファイルの形式を戻す
    image = cv2.imencode(".jpg", blur)[1].tobytes()

    # imgをgyazoにアップロード
    img = client.upload_image(image)
    sleep(8)
    test = client.get_image(image_id=img.image_id)
    # test.ocrがない場合はリトライ
    count = 0
    while test.ocr is None:
        sleep(4)
        test = client.get_image(image_id=img.image_id)
        # 3回リトライしてもダメならエラーを返す
        count += 1
        if count >= 3:
            return {"error": "OCR取得に失敗しました"}

    # imgのocrを取得
    print(test.ocr)

    # ocrを改行して整形
    ocr = test.ocr["description"].splitlines()

    return {"img_id": test.image_id, "ocr": ocr}

def compress_image_to_500kb(image: np.ndarray) -> np.ndarray:
    encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 90]
    result, enc_img = cv2.imencode('.jpg', image, encode_param)

    # Check if the compressed image size is less than or equal to 500KB
    while enc_img.nbytes > 500 * 1024:
        encode_param[1] -= 5  # Reduce the quality by 5
        result, enc_img = cv2.imencode('.jpg', image, encode_param)

    # Decode the compressed image back to a numpy array
    compressed_image = cv2.imdecode(enc_img, cv2.IMREAD_UNCHANGED)

    return compressed_image


from typing import List

from InquirerPy import inquirer
from InquirerPy.base.control import Choice
from pandas import DataFrame

from utils.todosit_api import get_all_projects, get_all_sections_for_project

days_of_week = [
    "Sunday",
    "Monday",
    "Tuesday",
    "Wednesday",
    "Thursday",
    "Friday",
    "Saturday",
]

async def get_user_action() -> str:
    """Method used to request to the user an action

    Returns:
        str: Requested user action
    """
    return await inquirer.select(
        message="How do you want to edit your todoist?",
        choices=[
            Choice("create", "Create new recurring task"),
            Choice("delete", "Delete a bunch of recurring stuff"),
        ],
    ).execute_async()

def flatten_array(arr):
    """Method used to flatten nested arrays

    Args:
        arr (List<Ant>): Nested array to flatten

    Returns:
        List<Any>: Flattened array
    """
    result = set()
    for sublist in arr:
        if isinstance(sublist, str):
            result.add(sublist)
        else:
            for item in sublist:
                result.add(item)
    return list(result)

async def get_new_task_info() -> dict:
    """Method used to collect all the new task information from the user

    Returns:
        dict: Dictionary containing all the new task information required to create it
    """
    new_task = dict()
    new_task["content"] = await inquirer.text(
        message="What is the new task you want to work on?"
    ).execute_async()
    new_task["days"] = await inquirer.checkbox(
        message="Pick your recurring days:",
        cycle=True,
        choices=[Choice(days_of_week, "Every day")]
        + [Choice(d, d) for d in days_of_week],
        validate=lambda result: len(result) >= 1,
        invalid_message="should be at least 1 selection",
        instruction="(select at least 1)",
    ).execute_async()

    new_task["days"] = flatten_array(new_task["days"])

    new_task["project_id"] = await inquirer.select(
        message="Select the project to which you want to assign these tasks:",
        default=None,
        choices=[Choice(p.id, p.name) for p in await get_all_projects()],
    ).execute_async()

    sections = await get_all_sections_for_project(new_task["project_id"])
    if sections:
        new_task["section_id"] = await inquirer.select(
            message="Select the section in project to which you want to assign these tasks:",
            default=None,
            choices=[Choice(s.id, s.name) for s in sections],
        ).execute_async()

    return new_task

async def get_delete_tasks_info(df: DataFrame) -> List[int]:
    """Method used to collect all the information about the task we want to delete

    Args:
        df (DataFrame): Dataframe with recurring tasks information along with a unique row identifier

    Returns:
        List[int]: List of all the Dataframe indexes that needs to be deleted. One index may contain multple task ids
    """
    indexes_to_delete = await inquirer.checkbox(
        message="Select recurring tasks to delete:",
        cycle=True,
        choices=[Choice(index, row["content"]) for index, row in df.iterrows()],
        validate=lambda result: len(result) >= 1,
        invalid_message="should be at least 1 selection",
        instruction="(select at least 1)",
    ).execute_async()

    proceed = await inquirer.confirm(
        message="Are you sure you want to delete these tasks?", default=False
    ).execute_async()
    return indexes_to_delete if proceed else None


from crop_label import *
image = np.array(Image.open('test_images/SARShip-1.0-30.tif'))
[cropped_images,ind] = crop_image(image, 416, 416, 2)
for i in range(len(cropped_images)):
    a=Image.fromarray(cropped_images[i])
    a.save("test_images/output"+str(i)+".tif")
print(cropped_images.shape)
labels=[]
with open("SARShip-1.0-30.txt") as f:
    for line in f:
        labels.append(line)
crop_label=crop_label(image,labels,3000,3000,416,416,2,ind)


import sys
sys.path.append(r'/home/pi/Desktop/Autonomous-Following-Drone/')
from fccontrolclass import FlightControllerCommands
from time import sleep

drone = FlightControllerCommands(throttle = 1000, yaw = 1500, roll = 1500)
drone.disarm()
drone.start()
for i in range(400):
    drone.throttle+=1
    sleep(0.03)
drone.constantmessage=False


import pickle
import time
from pynput import mouse
from pynput import keyboard

class MouseKeyboardRecorder:
    def __init__(self):
        self.events = []
        self.mouse_listener = None
        self.keyboard_listener = None
        self.last_click_time = 0  # 最後にクリックした時間を保存する変数
    # マウスの移動を受け取る関数
    def on_move(self, x, y):
        self.events.append(('mouse_move', x, y))

    # クリックイベントを受け取る関数
    def on_click(self, x, y, button, pressed):
        action = 'press' if pressed else 'release'
        current_time = time.time()  # 現在の時間を取得（秒単位）

        # 前回のクリックからの経過時間が0.5秒以下であれば、ダブルクリックとみなす
        if current_time - self.last_click_time <= 0.5:
            action = 'double_click'
            self.last_click_action = None  # ダブルクリックを検出したら、最後のクリックアクションをリセット
        else:
            self.last_click_action = 'single_click' if action == 'release' else None
        self.events.append(('mouse_click', x, y, button, action))

        # 最後にクリックした時間を更新
        self.last_click_time = current_time if action != 'double_click' else 0  # ダブルクリックの場合はリセット

    # スクロールイベントを受け取る関数
    def on_scroll(self, x, y, dx, dy):
        self.events.append(('mouse_scroll', x, y, dx, dy))

    # キーイベントを受け取る関数
    def on_key_press(self, key):
        try:
            self.events.append(('key_press', key.char))
        except AttributeError:
            # special keys
            self.events.append(('key_press', str(key)))
    # キーイベントを受け取る関数
    def on_key_release(self, key):
        if key == keyboard.Key.esc:
            self.stop()
        try:
            self.events.append(('key_release', key.char))
        except AttributeError:
            # special keys
            self.events.append(('key_release', str(key)))
    # 録画を開始する関数
    def start(self):
        self.mouse_listener = mouse.Listener(
            on_move=self.on_move,
            on_click=self.on_click,
            on_scroll=self.on_scroll)
        self.mouse_listener.start()

        self.keyboard_listener = keyboard.Listener(
            on_press=self.on_key_press,
            on_release=self.on_key_release)
        self.keyboard_listener.start()

    # 録画を終了する関数
    def stop(self):
        self.mouse_listener.stop()
        self.keyboard_listener.stop()
        return self.events

    def save_events_to_file(self, filename):
        with open(filename, 'wb') as file:
            pickle.dump(self.events, file)  # イベントをpickleファイルに保存

    @staticmethod
    def load_events_from_file(filename):
        with open(filename, 'rb') as file:
            events = pickle.load(file)  # pickleファイルからイベントを読み込み
        return events

if __name__ == '__main__':
    recorder = MouseKeyboardRecorder()
    try:
        recorder.start()
        recorder.mouse_listener.join()
        recorder.keyboard_listener.join()
    except KeyboardInterrupt:
        pass  # Ctrl+Cが押された場合、エラーを無視
    finally:
        recorder.save_events_to_file('events.pkl')  # イベントをpickleファイルに保存
        print('Events saved to events.pkl')  # 保存が完了したことを通知


# 0 또는 양의 정수가 주어졌을 때, 정수를 이어붙여 만들 수 있는 가장 큰 수 구하기
# numbers : 0 또는 양의 정수가 담긴 배열
# 가장 큰 수를 문자열로 return

def solution(numbers):
    numbers_str = [str(num) for num in numbers]
    numbers_str.sort(key=lambda x: x*3, reverse=True)

    return str(int(''.join(numbers_str)))

solution([6, 10, 2])


import sys

sys.path.append("../src")
sys.path.append("../lambda-loader/src")
import data

from default_alias import alias as default_alias
from default_channels import channels as default_channels
from leaderboardBot import LeaderBoardBot

def setup_production_environment(database, url):
    tables = [table.name for table in database.resource.tables.all()]

    if "player-alias-table" not in tables:
        database.create_support_table("player-alias-table", "Alias")

    if "channel-table" not in tables:
        database.create_support_table("channel-table", "ChannelName")

    if "daily-rating-record-table" not in tables:
        database.create_table("daily-rating-record-table")

    if "yesterday-rating-record-table" not in tables:
        database.create_table("yesterday-rating-record-table")


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

import os
import sys
import signal
import subprocess
import datetime
import socket
import time

# import csv
# import matplotlib.pyplot as plt
# import pandas as pd

import rospy

import numpy as np
import math

# from scipy.stats import norm
# from scipy.optimize import leastsq,least_squares
# from ekf_drps import EKF

from dji_sdk.msg import telemetry2, Packet, Packet2, Gimbal
from dji_sdk.msg import EscData, ESCStatusIndividual
from dji_sdk.srv import GetSingleBatteryDynamicInfo

from kios.msg import Telemetry, TerminalHardware, DroneHardware
from std_msgs.msg import String, Float64MultiArray
from sensor_msgs.msg import Imu, NavSatFix, BatteryState
from geometry_msgs.msg import Vector3Stamped, QuaternionStamped

from multimaster_msgs_fkie.msg import LinkStatesStamped

file_path = os.path.realpath(__file__)
currentDirectory = file_path.split('/')[-2]
file_path = file_path.split(currentDirectory, 1)[0] + 'src/dji_sdk/scripts/'
print(currentDirectory)
print(file_path)

# /home/kios/Documents/multimaster_db_matrice300_q3_demo/DRPS/ekffusion_drps_no_hackrf.py
sys.path.append(file_path)

def GetBoardID():
    f = open("/var/lib/dbus/machine-id", "r")
    boardID = f.read().strip()[0:4]
    # print(boardID)
    return boardID

boardId = GetBoardID()
dronename = '/matrice300' + '_' + boardId

print(dronename)

# dronename2='/matrice210RTK'
lat = 0  # import sensor data from ros
lon = 0
rawLat = 0
rawLon = 0
angularx = 0
angulary = 0
linearaccellxy = 0
headingangle = 0
gpsdat = np.zeros((2, 2))
velocitylinear = 0
altitude = 0
dataset = np.zeros((699, 25))
# def velocitycallback(messagedata):

# Drone
d_quat_x = 0
d_quat_y = 0
d_quat_z = 0
d_quat_w = 0
# Gimbal
g_yaw = 0
g_pitch = 0
g_roll = 0

meters_sum, x_sum, y_sum = 0, 0, 0
RPSarray2 = [0, 0]

batteryPercentage = 0
batteryVoltage = 0
batteryCurrent = 0
batteryCapacity = 0

def batteryCB(batteryStatus):
    global batteryPercentage, batteryVoltage, batteryCurrent, batteryCapacity
    batteryPercentage = batteryStatus.percentage
    batteryVoltage = batteryStatus.voltage
    batteryCurrent = batteryStatus.current
    batteryCapacity = batteryStatus.capacity

escCount = 0
escSpeed = []
escVoltage = []
escTemperature = []

def escMotorCB(escMotorStatus):
    global escCount, escSpeed, escVoltage, escTemperature
    # /matrice300_5807/ESC_data
    escCount = 0
    escSpeed = []
    escVoltage = []
    escTemperature = []

    for escMotor in escMotorStatus.esc:
        if escMotor.speed > 0:
            escCount += 1
            escSpeed.append(escMotor.speed)
            escVoltage.append(escMotor.voltage)
            escTemperature.append(escMotor.temperature)

gpssig = 0
satnumber = 0

# sequence number to count packet loss
seq = 0
global packlosspub, droneState, droneIDpub
droneState = "On Ground"
droneIdAck = False
droneIDpub = None

hostname = hostname = socket.getfqdn()
local_ip = socket.gethostbyname_ex(hostname)[2][0]
platform_ip = None

# print("Hostname:", hostname, "Local IP:", local_ip)

def signal_handler(sig, frame):
    global droneIDpub
    hello_msg = "{\"Timestamp\":\"" + str(rospy.get_rostime()) + "\",\"DroneName\":\"" + dronename.replace('/',
                                                                                '') + "\",\"Connected\":\"False\",\"Model\":\"MATRICE_300_RTK\",\"cameraVideoStreamSource\":\"unknown\",\"cameraName\":\"Zenmuse_H20T\"}"
    droneIDpub.publish(hello_msg)
    oc.rtmpHandler.deinitStream()
    print('Connected: False sent to platform.')
    sys.exit(0)

def EKF2_callback(rpsdata2):
    global RPSarray2
    RPSarray2 = rpsdata2.data

def vision_callback(flowdata):
    global meters_sum, x_sum, y_sum
    meters_sum, x_sum, y_sum = flowdata.data
    print("DRPS Vision data: ", meters_sum, x_sum, y_sum, flowdata.data)

def imucallback(messagedat):
    global angularx, angulary, linearaccellxy
    angularx = messagedat.angular_velocity.x
    angulary = messagedat.angular_velocity.y
    linearaccellxy = math.sqrt((messagedat.linear_acceleration.x) ** 2 + (messagedat.linear_acceleration.y) ** 2)

def telemetrycallback(teldat):
    global lat, lon, headingangle, velocitylinear, altitude, rostime, rostime_nano, fligth_time_seconds, batteryPercentage, gpssig, satnumber, home_lat, home_lon, drone_serial
    lat = teldat.latitude
    lon = teldat.longitude
    headingangle = teldat.heading
    velocitylinear = teldat.velocity
    altitude = teldat.altitude
    rostime = teldat.rostime_secs
    rostime_nano = teldat.rostime_nsecs
    fligth_time_seconds = teldat.flightTimeSecs
    batteryPercentage = teldat.batteryPercentage
    gpssig = teldat.gpsSignal
    satnumber = teldat.satelliteNumber
    home_lat = teldat.homeLatitude
    home_lon = teldat.homeLongitude
    drone_serial = teldat.serialVersionUID

def telemetrycallback_b(teldat2):
    global lat2, lon2, headingangle2, velocitylinear2, altitude2
    lat2 = teldat2.latitude
    lon2 = teldat2.longitude
    headingangle2 = teldat2.heading
    velocitylinear2 = teldat2.velocity
    altitude2 = teldat2.altitude

def rawgpscallback(raw):
    global rawLat, rawLon
    rawLat = raw.latitude
    rawLon = raw.longitude

def packetlosscb(data):
    global packlosspub
    print('ta start ine', data.start)
    db.create_tables([Data])
    print('print to for', data.fin - data.start)
    for i in range(data.fin - data.start, data.fin):
        print('to fin ine', data.fin)
        print('to seq ine', seq)
        print('to i ine', i)
        for test in Data.select().where(Data.seq == i):
            print('to test ine :', test)
            newpacket2 = Packet2()
            newpacket2.seq = test.seq
            newpacket2.serialVersionUID = test.serialVersionUID.encode('ascii', 'replace')

            print('to xameno packet ine:', newpacket2.seq)
            newpacket2.heading = test.head
            newpacket2.velocity = test.vel
            newpacket2.longitude = test.lon
            newpacket2.latitude = test.lat
            newpacket2.altitude = test.altitude
            newpacket2.date_time = test.date_time.encode('ascii', 'replace')
            newpacket2.rostime_secs = 0
            newpacket2.flightTimeSecs = int(test.fl_time)

            newpacket2.batteryThreshold = test.batteryThresh
            newpacket2.batteryPercentage = test.battery
            newpacket2.cpuTemp = test.cpuTemp
            newpacket2.gpuTemp = test.gpuTemp

            newpacket2.gpsSignal = test.gpssgnal
            newpacket2.satelliteNumber = test.gpssat
            newpacket2.homeLatitude = test.homLat
            newpacket2.homeLongitude = test.homLon

            # Drone Orientation
            newpacket2.d_quat_x = test.d_quat_x
            newpacket2.d_quat_y = test.d_quat_y
            newpacket2.d_quat_z = test.d_quat_z
            newpacket2.d_quat_w = test.d_quat_w
            # Gimbal Orientation
            newpacket2.g_yaw = test.g_yaw
            newpacket2.g_pitch = test.g_pitch
            newpacket2.g_roll = test.g_roll
            packlosspub.publish(newpacket2)

def DroneOrientationCB(msg):
    global d_quat_x, d_quat_y, d_quat_z, d_quat_w
    d_quat_x = msg.quaternion.x
    d_quat_y = msg.quaternion.y
    d_quat_z = msg.quaternion.z
    d_quat_w = msg.quaternion.w

def Gimbal_cb(gimbal):
    global g_yaw, g_pitch, g_roll
    g_yaw = gimbal.vector.z
    g_pitch = gimbal.vector.y
    g_roll = gimbal.vector.x

def GetJetsonCPUTemp():
    global cpuTemp
    f = open("/sys/class/thermal/thermal_zone0/temp", "r")
    cpuTemp = int(f.read().strip())
    return cpuTemp

def GetJetsonGPUTemp():
    f = open("/sys/class/thermal/thermal_zone1/temp", "r")
    gpuTemp = int(f.read().strip())
    return gpuTemp

# tegrastats
# RAM 2130/7774MB (lfb 1004x4MB) SWAP 0/3887MB (cached 0MB)
# CPU [11%@1190,2%@1190,1%@1190,1%@1190,1%@1190,2%@1190] EMC_FREQ 0% GR3D_FREQ 0%
# AO@31C GPU@31.5C PMIC@100C AUX@31.5C CPU@33C thermal@31.95C

# sudo tegrastats
# RAM 2387/7774MB (lfb 961x4MB) SWAP 0/3887MB (cached 0MB)
# CPU [14%@1190,9%@1190,2%@1190,4%@1190,0%@1190,1%@1344] EMC_FREQ 1%@1600 GR3D_FREQ 0%@114
# VIC_FREQ 0%@115 APE 150 MTS fg 0% bg 3%
# AO@31C GPU@31.5C PMIC@100C AUX@31.5C CPU@33C thermal@31.95C
# VDD_IN 3528/3569 VDD_CPU_GPU_CV 410/426 VDD_SOC 1107/1115
def GetTerminalHardware():
    # p = subprocess.Popen('tegrastats | head -n1', stdout=subprocess.PIPE, shell = True)
    p = subprocess.Popen(('tegrastats'), stdout=subprocess.PIPE)
    tegrastats_stdout = subprocess.check_output(('head', '-n1'), stdin=p.stdout)

    # tegrastats_stdout = p.stdout.readline()
    tegrastats_stdout = tegrastats_stdout.split()

    p.kill()
    # print(tegrastats_stdout)

    termHwPacket = TerminalHardware()
    termHwPacket.seq = seq
    termHwPacket.uid = GetBoardID()

    ram_str = tegrastats_stdout[1]
    # print(ram_str)
    ram_str = ram_str.replace('MB', '').split('/')
    # print(ram_str)

    termHwPacket.ram_use = int(ram_str[0])
    termHwPacket.ram_max = int(ram_str[1])

    swap_str = tegrastats_stdout[5]
    # print("swap_str", swap_str)
    swap_str = swap_str.replace('MB', '').split('/')
    # print("swap_str", swap_str)
    termHwPacket.swap_use = int(swap_str[0])
    termHwPacket.swap_max = int(swap_str[1])

    cached_swap_str = tegrastats_stdout[7]
    # print(cached_swap_str)
    cached_swap_str = cached_swap_str.replace('MB)', '')

    termHwPacket.swap_cache = int(cached_swap_str)

    emc_str = tegrastats_stdout[11]
    # print(emc_str)
    termHwPacket.emc_usage = int(emc_str.replace('%', ''))

    cpu_str = tegrastats_stdout[9]
    # print(cpu_str)
    cpu_str = cpu_str.replace('[', '').replace(']', '')
    cpu_str = cpu_str.split(',')

    cpu_core_usage = []
    cpu_core_freq = []
    for core in cpu_str:
        core_str = core.split('%@')
        cpu_core_usage.append(int(core_str[0]))
        cpu_core_freq.append(int(core_str[1]))

    termHwPacket.cpu_core_count = len(cpu_core_usage)

    termHwPacket.cpu_core_usage = cpu_core_usage
    termHwPacket.cpu_core_freq = cpu_core_freq

    # =============================================================================
    #     cpu_str_0 = cpu_str[0].split('%@')
    #     #print(cpu_str_0)
    #     termHwPacket.cpu_core0_usage = int(cpu_str_0[0])
    #     termHwPacket.cpu_core0_freq = int(cpu_str_0[1])
    #
    #     cpu_str_1 = cpu_str[1].split('%@')
    #     termHwPacket.cpu_core1_usage = int(cpu_str_1[0])
    #     termHwPacket.cpu_core1_freq = int(cpu_str_1[1])
    #
    #     cpu_str_2 = cpu_str[2].split('%@')
    #     termHwPacket.cpu_core2_usage = int(cpu_str_2[0])
    #     termHwPacket.cpu_core2_freq = int(cpu_str_2[1])
    #
    #     cpu_str_3 = cpu_str[3].split('%@')
    #     termHwPacket.cpu_core3_usage = int(cpu_str_3[0])
    #     termHwPacket.cpu_core3_freq = int(cpu_str_3[1])
    #
    #     cpu_str_4 = cpu_str[4].split('%@')
    #     termHwPacket.cpu_core4_usage = int(cpu_str_4[0])
    #     termHwPacket.cpu_core4_freq = int(cpu_str_4[1])
    #
    #     cpu_str_5 = cpu_str[5].split('%@')
    #     termHwPacket.cpu_core5_usage = int(cpu_str_5[0])
    #     termHwPacket.cpu_core5_freq = int(cpu_str_5[1])
    # =============================================================================
    termHwPacket.cpuTemp = GetJetsonCPUTemp()

    gr3d_str = tegrastats_stdout[13]
    termHwPacket.gr3d_usage = int(gr3d_str.replace('%', ''))

    #    gpu.0/devfreq/17000000.gv11b/cur_freq
    f = open("/sys/devices/gpu.0/devfreq/17000000.gv11b/cur_freq", "r")
    termHwPacket.gr3d_freq = int(f.readline()) / 1000000
    termHwPacket.gpuTemp = GetJetsonGPUTemp()
    f.close()

    return termHwPacket

def Create3dMesh():
    meshConstructorDir = '/home/jetson/Documents/mesh_construction/aidersplatform_algorithms_mesh_construction.py'

    # Move Some Files
    p = subprocess.Popen(('python', meshConstructorDir), stdout=subprocess.PIPE)
    p.wait()
    p.kill()

    print('Mesh Construction has finished')
    print('Posting 3d Mesh to platform')

    # Move some more

    # Post 3d mesh to platform

def DroneIdAckCB(ack):
    global droneIdAck

    print('Ack received', ack)

    if ack.data == '1':
        droneIdAck = True

def checkPortStatus(ip, port):
    p = subprocess.Popen(("nc", "-zvw5", ip, port), stderr=subprocess.PIPE)
    status = p.communicate()[1]

    print(str(status))

    # print (rc)
    # print (status)
    if 'succeeded' in str(status):
        return True
    else:
        return False

def findPlatformIp():
    print('Finding platform Ip...')
    platformIp = None

    while not platformIp:
        linkStats = rospy.wait_for_message('/master_discovery/linkstats', LinkStatesStamped)
        rosdevices = linkStats.links

        for device in rosdevices:
            if device.destination != local_ip:
                if checkPortStatus(device.destination, '8000') and checkPortStatus(device.destination, '1935'):
                    platformIp = device.destination
                    print("Platform Ip:", device)
                    return platformIp

        rospy.sleep(1)

def handshakePlatform():
    global droneIdPub, droneIdAckSub, droneIdAck

    droneIdAckSub = rospy.Subscriber(dronename + '/handshake', String, DroneIdAckCB)
    droneIdPub = rospy.Publisher('/droneIds', String, queue_size=2)

    hello_msg = "{\"Timestamp\":\"" + str(rospy.get_rostime()) + "\",\"DroneName\":\"" + dronename.replace('/',
                                                                                '') + "\",\"Connected\":\"True\",\"Model\":\"MATRICE_300_RTK\",\"cameraVideoStreamSource\":\"unknown\",\"cameraName\":\"Zenmuse_H20T\"}"
    timeout = 1000000
    print(hello_msg)
    for i in range(0, timeout):
        droneIdPub.publish(hello_msg)
        print('Attempt:\t' + str(i))
        rospy.sleep(5)

        if droneIdAck:
            print('Platform register Successful')
            droneIdAck = False
            return True

    if not droneIdAck:
        print('Could not register on platform.\n')
        return False

def setupTopics():
    global imuSub, rawGpsSub, gpsPub, droneOrientationSub, gimbalSub, terminalHwPub, droneHwPub
    global packlosspub, packetSub, packetPub2

    print('Setting up rostopics...')
    imuSub = rospy.Subscriber(dronename + '/imu', Imu, imucallback)

    rawGpsSub = rospy.Subscriber(dronename + '/raw_gps_position', NavSatFix, rawgpscallback)
    gpsPub = rospy.Publisher(dronename + '/GPSmeters', Float64MultiArray, queue_size=1)

    packlosspub = rospy.Publisher(dronename + '/PacketLoss', Packet2, queue_size=1)
    packetSub = rospy.Subscriber(dronename + '/Packet', Packet, packetlosscb)
    packetPub2 = rospy.Publisher(dronename + '/Packet2', Packet2, queue_size=1)

    droneOrientationSub = rospy.Subscriber(dronename + '/attitude', QuaternionStamped, DroneOrientationCB)
    gimbalSub = rospy.Subscriber(dronename + '/gimbal_angle', Vector3Stamped, Gimbal_cb)

    terminalHwPub = rospy.Publisher(dronename + '/TerminalHardware', TerminalHardware, queue_size=1)
    droneHwPub = rospy.Publisher(dronename + '/DroneHardware', DroneHardware, queue_size=1)

    batterySub = rospy.Subscriber(dronename + '/battery_state', BatteryState, batteryCB)
    escMotorSub = rospy.Subscriber(dronename + '/ESC_data', EscData, escMotorCB)
    print('Setting up rostopics FINISHED')

def publishTerminalHardware():
    hwPckt = GetTerminalHardware()
    terminalHwPub.publish(hwPckt)

def publishDroneHardware():
    global droneHwPub

    batteryTempSrv = rospy.ServiceProxy(dronename + '/get_single_battery_dynamic_info', GetSingleBatteryDynamicInfo)

    dhwPacket = DroneHardware()

    dhwPacket.seq = seq
    dhwPacket.uid = boardId

    dhwPacket.batteryThreshold = 10
    dhwPacket.batteryPercentage = int(batteryPercentage)
    dhwPacket.batteryTemperature = -69

    dhwPacket.batteryVoltage = int(batteryVoltage)
    dhwPacket.batteryCurrent = int(batteryCurrent)
    dhwPacket.batteryCapacity = int(batteryCapacity)

    dhwPacket.escCount = escCount
    dhwPacket.escSpeed = escSpeed
    dhwPacket.escVoltage = escVoltage
    dhwPacket.escTemperature = escTemperature

    droneHwPub.publish(dhwPacket)

if __name__ == '__main__':
    try:
        print('Initializing linknode...')
        rospy.init_node('linknode' + '_' + GetBoardID())

        rate = rospy.Rate(1)
        precision = 8
        np.set_printoptions(precision=precision)

        setupTopics()

        import telemetryTranslator as tt
        tt.listener(dji_name=dronename)

        import joyController as jc
        jc.listener(dji_name=dronename)

        while not rospy.is_shutdown():
            now = datetime.datetime.now()
            timestmp = now.strftime("%Y%m%d-%H:%M:%S.%s")
            rate.sleep()

    except rospy.ROSInterruptException:
        pass

#        platformIp = findPlatformIp()
#        if handshakePlatform():
#            signal.signal(signal.SIGINT, signal_handler)
#        else:
#            print('Could not shake hands with platform...\nExiting...\n')
#            exit(0)

#        print('Setting up Mission Middleware')
#        import telemetryTranslator as  tt
#        import csv2rosMission as mm
#        import orthocamera as oc
#
#        # Setup Mission Middleware
#        tt.listener(dji_name=dronename)
#        print('telemetryTranslator:\tReady')
#        rate.sleep()
#        mm.listener(dji_name=dronename)
#        print('csv2rosMission:\tReady')
#
#        oc.listener(platformIp, dji_name=dronename)
#        print('orthocamera:\tReady')
#        print('Middleware Setup:\tREADY')
#
#        db.connect()

# import joyController4 as jc
# jc.listener(dji_name=dronename)

#       series = pd.read_csv('TimeDelay.csv', header = 0, index_color = 0, parse_dates = True, squeeze = True)

#       series.plot(kind='kde')
#       series.savefig("TimeDelay.png")
#       series.show()
# ===================================================================================================

#	with open('droneActions1.txt', 'w') as f:
#	    f.writelines('latidute,longitude,altidute,velocity')
#	    f.writelines('\n')
#
#	lines = [lat2, lon2, altitude2, velocitylinear2]
#	with open('droneActions1.txt', 'a') as f:
#	    f.writelines([str(line) + "," for line in lines])
#	    f.writelines('\n')
# ===================================================================================================

#        db.close()


import time
import board
import displayio
from adafruit_progressbar.verticalprogressbar import (
    VerticalProgressBar,
    VerticalFillDirection,
)

# Make the display context
splash = displayio.Group()
board.DISPLAY.show(splash)

# set progress bar width and height relative to board's display
width = 10
height = board.DISPLAY.height - 40

x = width * 2
y = 10

# Create a new VerticalProgressBar object at (x, y)
vertical_progress_bar = VerticalProgressBar(
    (x, y), (width, height), direction=VerticalFillDirection.TOP_TO_BOTTOM
)

# Append progress_bar to the splash group
splash.append(vertical_progress_bar)

x = x * 2
# Create a second VerticalProgressBar object at (x+20, y)
vertical_progress_bar2 = VerticalProgressBar(
    (x, y), (width, height), direction=VerticalFillDirection.BOTTOM_TO_TOP
)

# Append progress_bar to the splash group
splash.append(vertical_progress_bar2)

current_progress = 0.0
while True:
    # range end is exclusive so we need to use 1 bigger than max number that we want
    for current_progress in range(0, 101, 1):
        print("Progress: {}%".format(current_progress))
        vertical_progress_bar.value = current_progress
        vertical_progress_bar2.value = current_progress
        time.sleep(0.05)
    time.sleep(0.3)
    vertical_progress_bar.value = vertical_progress_bar.minimum
    vertical_progress_bar2.value = vertical_progress_bar.minimum
    time.sleep(0.3)


from time import sleep
from DHP.context import warn, color
from DHP.Utils.cursor import connection, cursor
from DHP.Utils.logger import logger

cursor.execute("SHOW DATABASES;")
DataBases = cursor.fetchall()

def CreateTableUser():
    cursor.execute(
        """
    CREATE TABLE UserData(
        user_id SMALLINT PRIMARY KEY,
        user_name VARCHAR(20) NOT NULL,
        user_password VARCHAR(20) NOT NULL,
        user_power TINYINT NOT NULL
    )
    """
    )
    logger.warning("TABLE NOT FOUND | Created New Table UserData")
    warn(">> TABLE NOT FOUND | Created New Table UserData")

    cursor.execute(
        "INSERT INTO UserData values('5940', 'Harsh Patel', 'abcd1234',  '3');"
    )
    connection.commit()
    print(cursor.rowcount, "Record Inserted!!")
    sleep(1)

def CreateDataBase():
    cursor.execute("CREATE DATABASE SchoolMysqlProject")
    logger.warning("DataBase Not Found | Created New Database SchoolMysqlProject")
    warn(">> DataBase Not Found | Created New Database SchoolMysqlProject")

    sleep(1)

    cursor.execute("USE SchoolMysqlProject;")

    cursor.execute("SHOW TABLES;")
    Tables = cursor.fetchall()
    print(Tables)

    sleep(3)

    if ("UserData",) not in Tables:
        CreateTableUser()

    cursor.execute("SELECT * FROM UserData")
    TableData = cursor.fetchall()

    print(TableData)

def SetupUser():
    if ("schoolmysqlproject",) not in tuple(DataBases):
        print(tuple(DataBases))
        CreateDataBase()
    else:
        cursor.execute("use schoolmysqlproject;")
        cursor.execute("SELECT * FROM UserData")

        TableData = cursor.fetchall()
        if len(TableData) == 0:
            logger.critical(
                "TABLE FOUND EMPTY | ADDING DEFAULT VALUES | BUT HOW THE HELL THIS HAPPEN???"
            )
            cursor.execute("DROP TABLE UserData")
            CreateTableUser()

        print(color("DataBase Setup Done!"))
        logger.debug("INITIALIZATION OF DATABASE COMPLETE")
        logger.info("DB Changed | sys => schoolmysqlproject")


from rest_framework import serializers
from rest_framework.validators import UniqueValidator

from users.models import User

class UserSerializer(serializers.ModelSerializer):
    username = serializers.CharField(
        max_length=100,
        validators=[
            UniqueValidator(
                queryset=User.objects.all(), message="username already exists"
            )
        ],
    )
    is_seller = serializers.BooleanField(required=True)

    class Meta:
        model = User
        fields = [
            "username",
            "password",
            "first_name",
            "last_name",
            "is_seller",
            "date_joined",
            "is_superuser",
            "is_active",
        ]
        read_only_fields = [
            "date_joined",
            "is_active",
            "is_superuser",
        ]
        extra_kwargs = {"password": {"write_only": True}}

    def create(self, validated_data):
        return User.objects.create_user(**validated_data)

class UserIdSerializer(UserSerializer):
    class Meta:
        model = User
        fields = [
            "id",
            "username",
            "first_name",
            "last_name",
            "is_seller",
            "date_joined",
            "is_active",
            "is_superuser",
        ]

class UserPatchSerializer(UserSerializer):
    class Meta:
        model = User
        fields = [
            "id",
            "username",
            "first_name",
            "last_name",
            "is_seller",
            "date_joined",
            "is_active",
            "is_superuser",
        ]
        read_only_fields = [
            "date_joined",
            "is_active",
            "is_superuser",
        ]

class UserPatchAdminSerializer(UserSerializer):
    class Meta:
        model = User
        fields = [
            "id",
            "username",
            "first_name",
            "last_name",
            "is_seller",
            "date_joined",
            "is_active",
        ]
        read_only_fields = [
            "date_joined",
            "is_superuser",
        ]