import xml.etree.ElementTree as ET
from tqdm import tqdm
import numpy as np
import random
import matplotlib.pyplot as plt
import datetime
import time

# pip install -r requirements.txt

# Read the XML file and save the data in NumPy format. Note: one of brazil and burma must be True and the other False.
# Parse the XML file through xml.etree.ElementTree,
# create a numpy array with city_count*city_count dimensions, and save the read data into the array.
def readXml():
    if brazil:
        tree_brazil = ET.parse('brazil58.xml')
        root_brazil = tree_brazil.getroot()
        graph_element_brazil = root_brazil.find('graph')
        city_count_brazil = len(graph_element_brazil.findall('vertex'))
        # make use of a distance matrix denoted as D
        d_brazil = np.zeros((city_count_brazil, city_count_brazil), dtype=object)

        for vertex_idx, vertex_element in enumerate(graph_element_brazil.findall('vertex')):
            for edge_element in vertex_element.findall('edge'):
                cost = edge_element.get('cost')
                city_id = edge_element.text
                d_brazil[vertex_idx, int(city_id)] = float(cost)
        return d_brazil, city_count_brazil
    if burma:
        tree_burma = ET.parse('burma14.xml')
        root_burma = tree_burma.getroot()
        graph_element_burma = root_burma.find('graph')
        city_count_burma = len(graph_element_burma.findall('vertex'))
        # make use of a distance matrix denoted as D
        d_burma = np.zeros((city_count_burma, city_count_burma), dtype=object)

        for vertex_idx, vertex_element in enumerate(graph_element_burma.findall('vertex')):
            for edge_element in vertex_element.findall('edge'):
                cost = edge_element.get('cost')
                city_id = edge_element.text
                d_burma[vertex_idx, int(city_id)] = float(cost)
        return d_burma, city_count_burma

# compute fitness of every route
# The method is to traverse the array data,
# and add the distance between the last city and the first city
def CountF(p_list):
    s = 0
    for i in range(city_count - 1):
        s += data[p_list[i], p_list[i + 1]]
    s += data[p_list[-1], p_list[0]]
    return s

# 1. Generate an initial population of p randomly created solutions and assess the fitness of each individual in
# the population.
# Give a seed so that the random value returned each time is fixed
# The first column is the path, and the second column is the sum of the distances along the path.
def initial(list_range):
    p = np.zeros((list_range, 2), dtype=object)
    for i, j in zip(range(list_range), range(2023, 2023 + population_size)):
        random.seed(j)
        # 给出一个初始化的population
        initial_list = list(range(city_count))
        random.shuffle(initial_list)
        p[i, 0] = initial_list
        p[i, 1] = CountF(initial_list)
    return p

# 2. Use tournament selection twice to select two parents, denoted as a and b
# Select random numbers within the number of tournament_size non-repeating populations in the population,
# and select the one with the best result to return
def Tournament_Selection(p_list, count):
    random_t_1 = np.random.choice(population_size, count, replace=False)
    selected_values = population[random_t_1, 1]
    min_index = int(random_t_1[np.argmin(selected_values)])
    res_a = p_list[min_index, 0]

    np.random.seed(seed + np.random.choice(population_size, 1))
    random_t_2 = np.random.choice(population_size, count, replace=False)
    selected_values = population[random_t_2, 1]
    min_index = int(random_t_1[np.argmin(selected_values)])
    res_b = p_list[min_index, 0]
    return res_a, res_b

# 3. apply a Crossover_with_fix on these selected parents to generate two children, referred to as c and d.
# First select a random number so that the two subsets are truncated
# from the index of that number and exchange each other's data.
# When exchanging data here,
# pay attention to whether the values corresponding to the same index between a and b are equal.
# If they are not equal, it means there will be duplication. The duplicate data in c and d must be replaced.
def Crossover_with_fix(kid_a, kid_b):
    random_single_point = int(np.random.choice(city_count))
    kid_c = kid_a[:random_single_point] + kid_b[random_single_point:]
    kid_d = kid_b[:random_single_point] + kid_a[random_single_point:]
    for j in range(random_single_point, city_count):
        if kid_b[j] != kid_a[j]:
            kid_c[kid_c.index(kid_b[j])] = kid_a[j]
            kid_d[kid_d.index(kid_a[j])] = kid_b[j]
    return kid_c, kid_d

# 3. apply a OrderedCrossover on these selected parents to generate two children, referred to as c and d.
# Exchange data first, then add unique data later
def OrderedCrossover(kid_a, kid_b):
    random_single_point = int(np.random.choice(city_count))
    kid_c = kid_a[:random_single_point]
    kid_d = kid_b[:random_single_point]
    for j1 in kid_b:
        if j1 not in kid_c:
            kid_c.append(j1)
    for j2 in kid_a:
        if j2 not in kid_d:
            kid_d.append(j2)

    return kid_c, kid_d

# 4. Run a single_swap_mutation on c and d to give two new solutions e and f. Evaluate the fitness of e and f.
# Swap two points
def single_swap_mutation(m_c, m_d):
    random_e = np.random.choice(city_count, 2, replace=False)
    random_f = np.random.choice(city_count, 2, replace=False)
    m_e = m_c.copy()
    m_f = m_d.copy()

    m_e[random_e[0]], m_e[random_e[1]] = m_e[random_e[1]], m_e[random_e[0]]
    m_f[random_f[0]], m_f[random_f[1]] = m_f[random_f[1]], m_f[random_f[0]]

    return m_e, m_f

# 4. Run a inversion on c and d to give two new solutions e and f. Evaluate the fitness of e and f.
# Slice at random values, then flip the data after that
def inversion(m_c, m_d):
    random_e = np.random.choice(city_count)
    random_f = np.random.choice(city_count)
    m_e = m_c.copy()
    m_f = m_d.copy()

    m_e = m_e[:random_e] + list(reversed(m_e[random_e:]))
    m_f = m_f[:random_f] + list(reversed(m_f[random_f:]))
    return m_e, m_f

# 4. Run a multiple_swap_mutation on c and d to give two new solutions e and f. Evaluate the fitness of e and f.
# Swap multiple points
def multiple_swap_mutation(m_c, m_d, count):
    random_e = np.random.randint(0, city_count, count)
    random_f = np.random.randint(0, city_count, count)
    m_e = m_c.copy()
    m_f = m_d.copy()
    for g in range(count // 2):
        m_e[random_e[g]], m_e[random_e[-(g + 1)]] = m_e[random_e[-(g + 1)]], m_e[random_e[g]]
        m_f[random_f[g]], m_f[random_f[-(g + 1)]] = m_f[random_f[-(g + 1)]], m_f[random_f[g]]

    return m_e, m_f

# 5. Run Replace_Weakest function, firstly for e,        then f
# Replace the value of the worst data in the list
def Replace_Weakest(fit_list):
    fit_score = CountF(fit_list)
    sorted_idx = np.argsort(-population[:, 1])
    if fit_score < population[sorted_idx[0], 1]:
        population[sorted_idx[0], 0], population[sorted_idx[0], 1] = fit_list, fit_score

# 5. Run Replace_FirstWeakest function, firstly for e, then f
# Replace the first value lower than the current value
def Replace_FirstWeakest(fit_list):
    fit_score = CountF(fit_list)
    for h in range(population_size):
        if population[h, 1] >= fit_score:
            population[h, 0], population[h, 1] = fit_list, fit_score
            break

result = []
mutation_count_list = []
tournament_size_list = []

seed = 2000  # Seed value for random number generation
mutation_count = 2  # Number of mutation operations if 10 exchange 5 times
tournament_size = 4
population_size = 10

brazil = True  # Flag for using Brazil data
burma = False  # Flag for using Burma data
data, city_count = readXml()  # Read data from XML files and get the city count
population = initial(population_size)  # Initialize the population

# Flags for different states
Crossover_with_fix_state = False  # Whether to enable Crossover_with_fix
OrderedCrossover_state = True  # Whether to enable OrderedCrossover
single_swap_mutation_state = False  # Whether to enable single swap mutation
inversion_state = True  # Whether to enable inversion mutation
multiple_swap_mutation_state = False  # Whether to enable multiple swap mutation
Replace_FirstWeakest_state = True  # Whether to enable replacing the first weakest individual
Replace_Weakest_state = False  # Whether to enable replacing the weakest individual

use_cross = True  # Whether use crossover
save_pic_state = False  # Whether save picture

start_time = time.time()
steps = 10000
# start to loop
for step in tqdm(range(steps)):
    np.random.seed(seed)
    # if step == 2000:
    #     mutation_count = 6
    # if step == 6000:
    #     mutation_count = 2
    # if step == 6000:
    #     tournament_size = 6
    a, b = Tournament_Selection(population, tournament_size)
    if use_cross:
        if Crossover_with_fix_state:
            c, d = Crossover_with_fix(a, b)
        if OrderedCrossover_state:
            c, d = OrderedCrossover(a, b)
    if not use_cross:
        c, d = a.copy(), b.copy()
    if single_swap_mutation_state:
        e, f = single_swap_mutation(c, d)
    if inversion_state:
        e, f = inversion(c, d)
    if multiple_swap_mutation_state:
        e, f = multiple_swap_mutation(c, d, mutation_count)
    if Replace_FirstWeakest_state:
        Replace_FirstWeakest(e)
        Replace_FirstWeakest(f)
    if Replace_Weakest_state:
        Replace_Weakest(e)
        Replace_Weakest(f)
    score = np.sum(population[:, 1]) / population_size
    result.append(score)
    mutation_count_list.append(mutation_count)
    tournament_size_list.append(tournament_size)
    seed = seed + 1
end_time = time.time()

y = min(population[:, 1])
z = np.argmin(population[:, 1])
x = list(range(0, steps))
current_time = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S')

plt.figure(figsize=(10, 8))
plt.subplots_adjust(hspace=0.3)
city = ""
if brazil:
    city = "Brazil"
elif burma:
    city = "Burma"
plt.subplot(2, 1, 1)
plt.xlabel('step')
plt.ylabel('sum population cost')
plt.title(f'city:{city},min_value:{y},m_count:{mutation_count},t_count:{tournament_size},len_p:{population_size}')
plt.plot(x, result, 'r-', lw=3)
plt.legend(['result'])

plt.subplot(2, 2, 3)
plt.plot(x, mutation_count_list, 'g-', lw=3)
plt.xlabel('step')
plt.ylabel('mutation_count')
plt.legend(['mutation_count'])

plt.subplot(2, 2, 4)
plt.plot(x, tournament_size_list, 'b-', lw=3)
plt.xlabel('step')
plt.ylabel('kid_count')
plt.legend(['kid_count'])
if save_pic_state:
    plt.savefig(f'{city}_{current_time}.png')
plt.show()
plt.close()
print(f'min value of {city} is {population[z, 1]}\nthe route is {population[z, 0]} ')
# Calculate the time difference
elapsed_time = end_time - start_time
print(f"Elapsed time: {elapsed_time} seconds")


from datetime import datetime
from zipfile import ZipFile
from pymongo import MongoClient
import os
import logging
import pytz

from etl.extract.feed_service import fetch_geopackage_feed
from etl.extract.feed_service import download_zip
from etl.load.mongodb.mongo_helpers import initiliaze_source_document

log = logging.getLogger(__name__)

def unzip(path, to_path, to_filename):
    with ZipFile(path, allowZip64=True) as zf:
        zf.extract(to_filename, to_path)

def process_geopackage(reg_type):
    doc_type = reg_type.type_name
    log.info("Collecting for type: '%s'" % doc_type)

    try:
        mongoUrl = os.environ.get('mongodbUrl')
        client = MongoClient(mongoUrl)
        db = client.bro
    except Exception as e:
        log.error(str(e))
        return

    # Get geopackage ATOM feed based on source URL
    try:
        source_url = os.environ.get(reg_type.sourceKey)
        feed = fetch_geopackage_feed(source_url)
        db.source.update_one({"type": doc_type}, {
                             "$set": {"last_extracted": datetime.now()}}, upsert=True)
    except Exception as e:
        log.error(str(e))
        db.source.update_one({"type": doc_type}, {
                             "$set": {"status": "Failed extracting xml"}}, upsert=True)
        return

    # Download and process ZIP from source
    try:
        source = db.source.find_one({"type": doc_type})
        log.info("Datum in feed: %s en laatst update datum: %s." %
                 (feed.updated, source['updated']))

        download_data = feed.updated > pytz.utc.localize(source['updated'])

        if download_data:

            download_location = os.environ.get('downloadLocation', '/mnt/brodata/')
            path = download_location + feed.filename

            log.info("Start download van %s naar %s" % (feed.zip_url, path))
            if download_zip(feed.zip_url, path):
                unzip_filename = feed.filename.replace('zip', 'gpkg')
                log.info("Unzipping %s" % path)
                if doc_type == "bhr-gt":
                    unzip_filename = "brobhrgtvolledigeset.gpkg"
                unzip_location = os.environ.get('unzipLocation', '/mnt/brodata/')
                unzip(path, unzip_location, unzip_filename)

                db.source.update_one({"type": doc_type},
                                     {"$set": {"updated": feed.updated,
                                               "status": "OK", "zip_filename": feed.filename}},
                                     upsert=True)
                log.info("Extracted geopackage for type: %s" % doc_type)
    except Exception as e:
        log.error(str(e))
        db.source.update_one({"type": doc_type}, {
                             "$set": {"status": "Failed extracting gpkg"}}, upsert=True)
        return


import pandas as pd
import numpy as np
import cvxpy as cp
import scipy.optimize as opt

def mean_variance_opt(df_mean,df_cov):
    assets = df_mean.index
    ret = df_mean.values
    cov = df_cov.values
    n = len(assets)
    w = cp.Variable(n)
    objective = cp.Minimize(cp.quad_form(w,cov))
    constraints = [w>=0]
    constraints += [ret @ w >= 0.1]
    problem = cp.Problem(objective,constraints)
    problem.solve()
    results = w.value/sum(w.value)
    return pd.Series(results,index=assets)

def risk_parity_alternative(df_cov):
    assets = df_cov.index
    cov = df_cov.values
    n = len(assets)
    w = cp.Variable(n)
    target = 0
    p_variance = w.T @ cov @ w
    for i in range(n):
        denominator = cov[i,:] @ w * n
        target += (w[i] - p_variance/denominator)**2
    constraints = [w>=0,sum(w)== 1 ]
    objective = cp.Minimize(target)
    problem = cp.Problem(objective,constraints)
    problem.solve()
    return pd.Series(w.value, index=assets)

def risk_parity(df_cov):

    assets = df_cov.index
    cov = df_cov.values
    n = len(assets)
    w0 = np.repeat(1/n,n)
    A = np.repeat(1,n)[np.newaxis,:]
    lb = np.array([1])
    ub = np.array([1])
    constraints = opt.LinearConstraint(A=A,lb=lb,ub=ub)
    bounds = opt.Bounds(ub=np.repeat(np.inf,n),lb=np.repeat(0,n))
    def target(w):
        target = 0
        p_variance = w.T.dot(cov).dot(w)
        for i in range(n):
            denominator = cov[i, :].dot(w) * n
            target += (w[i] - p_variance / denominator) ** 2
        return target

    res = opt.minimize(target,w0,method='SLSQP',constraints=constraints,bounds=bounds)

    return pd.Series(res.x, index=assets)

df_meta = pd.read_excel(r'C:\Users\mrzha\OneDrive\Documents\AssetAllocation\Asset Allocation Low Risk.xlsx',
                        sheet_name='Candidate', index_col='Index')
df_meta['Fund ID'] = df_meta['Fund ID'].map(lambda x: '0' * (6 - len(str(x))) + str(x))
fund_list = df_meta['Fund ID']
fund_name = df_meta['Fund Name']
fund_mapping = dict(zip(fund_list, fund_name))

df = pd.read_csv(r'C:\Users\mrzha\OneDrive\Documents\AssetAllocation\Fund Return\Low Risk Return.csv',index_col=0,parse_dates=['Date'])
df.columns = df.columns.map(lambda x: '0'*(6-len(str(x)))+str(x))
candidates = ['003327','000171','000215','519062']
df = df[candidates]
df_month = df.resample('M').last()
df_month = df_month.pct_change()
date = '2020/01/31'

df_ewcorr = df_month.ewm(halflife=60,min_periods=36).corr().loc[date]
df_ewcov = df_month.ewm(halflife=60,min_periods=36).cov().loc[date]
df_ewcorr.index = df_ewcorr.index.get_level_values(1)
df_ewcov.index = df_ewcov.index.get_level_values(1)
df_mean = df_month.mean()
df_cov = df_ewcov.dropna(axis=1).dropna(axis=0)
df_mean = df_mean.reindex(df_cov.index)

results = pd.DataFrame(index=candidates)
results.loc[:,'fund_name'] = results.index.map(lambda x: fund_mapping[x])
results.loc[:,'return'] = 12*df_mean
results.loc[:,'vol'] = np.sqrt(12)*df_month.std()
results.loc[:,'ret over risk'] = results.loc[:,'return']/results.loc[:,'vol']
results.loc[:,'mean_variance_optimization'] = mean_variance_opt(df_mean,df_cov)
results.loc[:,'risk_parity'] = risk_parity(df_cov)

results.to_excel(r'C:\Users\mrzha\OneDrive\Documents\AssetAllocation\LowRiskAllocationResults.xlsx')


import sys
import os
sys.path.append(os.getcwd())

import matplotlib.pyplot as plt
from datetime import datetime
from src.models.utils.logger import Logger

trainings = [
	("bc", "BC"),
	("pg", "PG"),
	("ppo", "PPO"),
	("ppo_lstm", "PPO w/ LSTM"),
	("ppo_attention", "PPO w/ AttentionNet"),
]

print("Alg", "Epochs", "Time", "Avg. Lifespan", "Max Lifespan")
for training in trainings:
	log_name = training[0]
	log_title = training[1]

	logs_path = os.path.join('logs', log_name, log_name + '0.log')
	if not os.path.exists(logs_path):
		print("Log file '{0}' not found.".format(logs_path))
		continue
	training_logs = Logger.read(logs_path)

	training_time = datetime.fromtimestamp(training_logs[-1]['timestamp']) - datetime.fromtimestamp(training_logs[0]['timestamp'])
	print(log_title, len(training_logs), training_time, training_logs[-1]['custom_metrics']['avg_lifespan_mean'], training_logs[-1]['custom_metrics']['max_lifespan_mean'])

	avg_lifespans = [training_log['custom_metrics']['avg_lifespan_mean'] for training_log in training_logs]
	max_lifespans = [training_log['custom_metrics']['max_lifespan_mean'] for training_log in training_logs]
	epochs = range(1,len(training_logs)+1)
	fig = plt.figure(dpi=1200)
	plt.plot(epochs, avg_lifespans, 'g', label='Avg. Lifespans')
	plt.plot(epochs, max_lifespans, 'b', label='Max Lifespans')
	plt.title(log_title + " Lifespans over Training")
	plt.xlabel('Epochs')
	plt.ylabel('Agent Iters Alive')
	plt.legend()
	# plt.show()
	plt.savefig(log_name + "_fig.png")
	plt.close(fig)


from flask import jsonify
from flask.views import MethodView
from flask_jwt_extended import jwt_required
from flask_smorest import Blueprint
from flask_smorest import abort
from sqlalchemy.exc import SQLAlchemyError
from stores.extensions.database import ProductModel
from stores.extensions.database import StoreModel
from stores.extensions.database import TagModel
from stores.extensions.database import db
from stores.extensions.schemas import TagSchema

blp = Blueprint("tag", __name__, description="Department tag operations")

@blp.route("/tag/<int:tag_id>")
class Tags(MethodView):
    """Tags operations"""

    @blp.response(200, TagSchema)
    def get(self, tag_id):
        """Get tag by ID"""
        tag = TagModel.query.get_or_404(tag_id, description="Tag id not found")
        return tag

    # @blp.arguments(TagUpdateSchema)
    @blp.response(200, TagSchema)
    def put(self):
        """Update tag by ID"""
        raise NotImplementedError

    @jwt_required(fresh=True)
    @blp.response(204, description="Deletes the tag if not linked to a product")
    @blp.alt_response(400, description="Abort if the tag is associated to a product")
    def delete(self, tag_id):
        """Delete tag by ID"""
        tag = TagModel.query.get_or_404(tag_id, description="Tag id not found")

        if not tag.products:
            db.session.delete(tag)
            db.session.commit()
        else:
            abort(400, message="The given tag is associated to a product and could not be deleted")

@blp.route("/stores/<string:store_id>/tag")
class StoreTags(MethodView):
    """Tags operations based on stores"""

    @blp.response(200, TagSchema(many=True))
    def get(self, store_id):
        """Get all department tags from the given store"""
        store = StoreModel.query.get_or_404(store_id, description="Store id not found")
        return store.tags

    @jwt_required()
    @blp.arguments(TagSchema)
    @blp.response(201, TagSchema)
    def post(self, data, store_id):
        """Create a tag in a store"""
        if TagModel.query.filter(
            TagModel.store_id == store_id, TagModel.name == data["name"]
        ).first():
            abort(400, message="Tag name already exists in that store")

        tag = TagModel(**data, store_id=store_id)

        try:
            db.session.add(tag)
            db.session.commit()
        except SQLAlchemyError as error:
            abort(500, message=f"Error {error} while inserting tag to Store {id}")
        return tag

@blp.route("/products/<int:product_id>/tag/<int:tag_id>")
class ProductTags(MethodView):
    """Products and tags link operations"""

    @jwt_required()
    @blp.arguments(TagSchema)
    @blp.response(201, TagSchema)
    def post(self, product_id, tag_id):
        """Link a department tag to a product"""
        product = ProductModel.query.get_or_404(product_id, description="Product id not found")
        tag = TagModel.query.get_or_404(tag_id, description="Tag id not found")

        product.tags.append(tag)

        try:
            db.session.add(product)
            db.session.commit()
        except SQLAlchemyError as error:
            abort(
                500, message=f"Error {error} while linking Tag {tag_id} and Product {product_id}"
            )

        return tag

    @jwt_required()
    @blp.response(200)
    def delete(self, product_id, tag_id):
        """Unlink a tag from a product"""
        product = ProductModel.query.get_or_404(product_id, description="Product id not found")
        tag = TagModel.query.get_or_404(tag_id, description="Tag id not found")

        product.tags.remove(tag)

        try:
            db.session.add(product)
            db.session.commit()
        except SQLAlchemyError as error:
            abort(
                500, message=f"Error {error} while linking Tag {tag_id} and Product {product_id}"
            )

        return jsonify(message="Tag and product were unlinked", product=product, tag=tag)


from typing import List
from fastapi import APIRouter

from schemas.season import Season

router = APIRouter()

@router.get("/seasons", response_model=List[Season])
async def get_seasons():
    return True

@router.post("/seasons")
async def create_season(season: Season):
    db["seasons"].append(season)
    return True

@router.get("/seasons/{id}")
async def get_season():
    return True

@router.get("/seasons/{id}/episodes")
async def get_episodes_from_season():
    return True


# encoding:utf-8

import matplotlib.pyplot as plt
from matplotlib import rcParams

rcParams['font.family'] = 'SimHei'

# 如果要保存为pdf格式，需要增加如下配置
#rcParams["pdf.fonttype"] = 42

X = [2000,3000,4000]
DT = [0.92,0.93,0.94]
SVM = [0.83,0.84,0.87]
Logistic = [0.82,0.83,0.94]
KNeighbors = [0.72,0.75,0.76]
GaussianNB = [0.6,0.65,0.65]

plt.plot(X,DT,label='y2',color='r',linewidth=2)
plt.plot(X,SVM,label='y3',color='b',linewidth=2)
plt.plot(X,Logistic,label='y4',color='k',linewidth=2)
plt.plot(X,KNeighbors,label='y5',color='c',linewidth=2)
plt.plot(X,GaussianNB,label='y5',color='m',linewidth=2)

plt.xlabel(u'数据集网址数量(个)')
plt.ylabel(u'预测正确率')
plt.title(u'五种分类算法正确率比较')
plt.legend()

plt.show()

# plt.bar(x,y,label="one",color='blue') # 住装图
# plt.bar(x2,y2,label="sec",color='red')

# plt.plot(x2,y2,label="second") # 线装图
# plt.plot(x,y,label="first")

# population_ages = [22,23,35,45,32,65,44,12,110,130,33,45,67,87,33,33]

# ids = [x for x in range(len(population_ages))]

# bins = [0,10,20,30,40,50,60,70,80,90,100,120,130,140]
#
# plt.hist(population_ages,bins,histtype='bar',rwidth=0.8,label='populat') # 直方图

# x = [1,2,3,4,5,6,7,8]
#
# y = [2,5,6,7,5,4,7,5]
# plt.scatter(x,y,label="skitscat",color='k',marker="*",s=50) # 散点图

# days = [1,2,3,4,5]
# sleeping = [5,6,4,8,2]
# eating = [2,3,5,6,5]
# working = [7,8,9,6,6]
# playing = [5,6,7,8,7]
# plt.plot([],[],color='m',label='sleeping',linewidth=3)
# plt.plot([],[],color='c',label='eating')
# plt.plot([],[],color='r',label='woring')
# plt.plot([],[],color='k',label='playing')
#
# plt.stackplot(days,sleeping,eating,working,playing,colors=['m','c','r','k']) #堆叠式图区

# slices = [7,2,2,13]
# activities = ['sleeping','eating','working','playing']
# colors = ['c','m','r','b']
# plt.pie(slices,
#         labels=activities,
#         colors=colors,
#         startangle=90,
#         shadow=True,
#         explode=(0,0.1,0,0),
#         autopct='%1.1f%%'
#         )


import argparse
import itertools
import logging
from pprint import pprint
from typing import List, Dict

import PIL
from PIL import Image
import time
import sys

import mss
from mss import models
from mss.screenshot import ScreenShot

import espixelstick
from mapping import PixelAddress, PixelStrip
import img_proc

import signal
import sys

from region import ScreenRegion, CombineRegion

def signal_handler(sig, frame):
    print('Exiting...')

    # this doesn't turn off the leds for some reason
    # TODO: shut off the LEDs when we exit
    for i in range(1, 3):
        if sender[i] is not None:
            sender[i].dmx_data = (0, 0, 0, 0)

    sender.stop()  # do not forget to stop the sender
    sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)

def send_data(sender, pixel_strips: List[PixelStrip], save_image):
    # Turn off automatic flushing so we can send everything at the same time
    sender.manual_flush = True
    for pixel_strip in pixel_strips:
        pixel_data = []
        for region in pixel_strip.regions:
            img = region.capture_and_resize(pixel_strip.max_row_length, pixel_strip.rows, save_image)
            pixel_data += img_proc.create_color_data(img, pixel_strip, region)

        # print number of pixels
        # print(len(pixel_data)/4)

        # Set pixel data for the universe
        sender[pixel_strip.universe].dmx_data = pixel_data

    # Flush all data
    sender.flush()

    # Reenable automatic flushing
    sender.manual_flush = False

def flatten(l: List) -> List:
    return list(itertools.chain.from_iterable(l))

# Send a solid color that changes every 2s
# This doesn't use the pixel mapping structure, it just spams solid colors to the DMX
# universes defined in 'pixel_strips'.  Tests the physical LED wiring and controller setup
# ONLY (does not test the pixel mapping)
def test_strips(pixel_strips):
    sample_data = {
        "red": (255, 0, 0, 0) * 300,
        "green": (0, 255, 0, 0) * 300,
        "blue": (0, 0, 255, 0) * 300,
    }
    color_iter = itertools.cycle(sample_data.values())

    for i in range(20):
        color_data = next(color_iter)
        for pixel_strip in pixel_strips:
            sender[pixel_strip.universe].dmx_data = color_data

        time.sleep(1)

    time.sleep(10)
    sender.stop()

# Turn off the LEDs
def strips_off(pixel_strips):
    print("Turning strips off")
    for pixel_strip in pixel_strips:
        sender[pixel_strip.universe].dmx_data = (0, 0, 0, 0) * 1000
    sender.stop()
    print("Turned strips off.  This doesn't always exit, you might need to press ctrl+c again")

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

parser = argparse.ArgumentParser(description='esp-based bias lighting')
parser.add_argument('--debug', dest='debug', action='store_true', default=False, help='debug mode (print debug logs)')
parser.add_argument('--test', dest='test', action='store_true', default=False, help='test mode (spam solid colors)')
parser.add_argument('--slow', dest='slow', action='store_true', default=False, help='slow mode (3 fps)')
parser.add_argument('--save', dest='save', action='store_true', default=False, help='save png image files for debugging')
parser.add_argument('--off', dest='off', action='store_true', default=False, help='turn strips off')
parser.add_argument('--profile', dest='profile', action='store_true', default=False, help='profile (create cProfile profile for debugging performance)')
# parser.add_argument('--fps', dest='fps', action='store', default=30, help='fps')
args = parser.parse_args()

if args.debug:
    print("DEBUG MODE ENABLED")
    logging.basicConfig(level=logging.DEBUG)

frame_rate = 3 if args.debug or args.slow else 30

# I probably don't wanna do the sleep time thing, because this doesn't at all take
# into account how long it took to process the images.  probably responsible
# for some of the choppiness.  replace with asyncio or something like timeloop
# TODO: try out this and see if it helps: https://github.com/sankalpjonn/timeloop
sleep_time = round(1/frame_rate, 3)-.001

### A lot of the code below is very specific to my specific pixel setup.  The setup consists of:
# LED type: these are SK6812 LEDs which are RGBW.  This is what I already had in channels w/ connectors
# I would have preferred to use APA102 LEDs but I didn't have them in channels.  The RGBW LEDs require 4 DMX channels per light
# which reduces the number of LEDs we can have in a DMX Universe.  That's definitely a downside to these LEDs
# (DMX universes can have 512 lights, and each individual LED is RGBW=4x lights).
#
# 3 distinct LED fixtures
# - each fixture uses 1 esp8266 (dev board)
#
# - right monitor
#   - dmx universe 1
#   - 4 rows x 29 pixels in horizontal zigzag pattern starting at lower left
#
# - left monitor
#   - dmx universe 2
#   - 4 rows x 29 pixels in horizontal zigzag pattern starting at lower left
#
# - desk
#   - dmx universe 3+4
#   - 3 rows, horizontal zigzag, starting at upper right
#   - row #1 (dmx universe 3)
#     - back of desk, 75 pixels
#   - row #2 - first part - 53 pixels in universe #3
#   - row #2 - second part - 18 pixels in universe #4
#     - row 2 is split due to universe size limit
#   - row #3 - 71 pixels (dmx universe 4)
#     - row #2 and #3 are in the middle of the desk facing downwards

# function to determine if a specific pixel falls into a specific region
# used for the monitors which have 4x rows of 29 pixels each
# this is how we determine which LEDs should get the top of a screen vs the bottom of a screen
# this functionality should really be refactored to use the newer ScreenRegion class
def _region_fn_monitors(pixel: PixelAddress) -> str:
    if pixel.index < 29*2:
        return "bottom"
    else:
        return "top"

mss_instance = mss.mss()

regionTop3 = ScreenRegion("top", 3, mss_instance)
regionBottom3 = ScreenRegion("bottom", 3, mss_instance)
regionTop1 = ScreenRegion("top", 1, mss_instance)
regionBottom1 = ScreenRegion("bottom", 1, mss_instance)
allBottom = CombineRegion("bottom", 1, mss_instance)

# The list of pixels strips.  The PixelStrip has kind of grown into a catch-all for a bunch of functionality & data
pixel_strips = [
    # 192.168.1.237
    PixelStrip(
        strip_addr="192.168.1.237", universe=1, row_length=[29,29,29,29], rows=4, start_left=True,
        start_bottom=True, region_fn=_region_fn_monitors,
        regions=[regionBottom3, regionTop3],
    ),

    PixelStrip(
        strip_addr="192.168.1.240", universe=2, row_length=[29,29,29,29], rows=4, start_left=True,
        start_bottom=True, region_fn=_region_fn_monitors,
        regions=[regionBottom1, regionTop1],
    ),

    PixelStrip(
        strip_addr="192.168.1.243", universe=3, row_length=[75, 53], rows=2, start_left=False,
        start_bottom=False, region_fn=lambda _: "bottom",
        regions=[allBottom],
    ),

    # # 29 in first channel
    # # 42 in second in 2nd channel
    ## 24 in second channel that are part of universe 3
    # # 29+24 in universe 3, remainder (18) in universe 4
    # # 71 total
    # This one has the most complicated mapping due to the mismatched row lengths and that
    # it actually encompasses multiple DMX universes :/
    # the mapping doesn't work 100% here yet, there's something wrong with the offset calculations
    # in mapping.py.  its a few pixels off.  it could also be that we don't handle matrices with
    # multiple different row_lengths correctly when mapping screen pixels to led pixels
    PixelStrip(
        strip_addr="192.168.1.243", universe=4, row_length=[18, 71], rows=2, start_left=True,
        start_bottom=False, region_fn=lambda _: "bottom",
        regions=[allBottom], first_pixel_offset=53, max_row_length=71,
    ),
]

sender = espixelstick.create_sender(pixel_strips, fps=frame_rate)

if args.profile:
    for i in range(0, 100):
        send_data(sender, pixel_strips, save_image=args.save)
        time.sleep(sleep_time)

    sender.stop()
    sys.exit(0)

if args.test:
    test_strips(pixel_strips)
    sys.exit(0)

if args.off:
    strips_off(pixel_strips)
    sys.exit(0)

# for i in range(0, 1000):
while True:
    send_data(sender, pixel_strips, save_image=args.save)
    time.sleep(sleep_time)


import numpy as np
import pandas as pd
import cv2
import glob

img_list = glob.glob("../Data/img_align_celeba/*.jpg")
img_data = []

for i in range(len(img_list)):
    img_file = img_list[i]
    img = cv2.imread(img_file)
    gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    gray_img = gray_img[20:198,:]
    gray_img = cv2.resize(gray_img, (32,32), interpolation=cv2.INTER_AREA)
    gray_img_list = np.ravel(gray_img).tolist()
    img_data.append(gray_img_list)
    if (i%100)==0:
        print("Converted {}/{}".format(i+1,len(img_list)))
    if ((i+1)%16277)==0:
        img_df = pd.DataFrame(img_data)
        img_df.to_csv("../Data/celeba_grayscale_32/train_{:02d}.csv".format((i+1)//16277),header=False,index=False)
        img_data = []
        if((i+1)//16277)==10:
            break


import cv2
import numpy as np
import os

def random_centers(K, dim):
    res = []
    for k in range(0,K):
        vec=[]
        for i in range(0,dim):
            vec.append(np.random.uniform(-1, 1))
        res.append(vec)
    return(res)

def cluster_points(X, mu):
    clusters  = {}
    for i in range(0, len(mu)):
        clusters[i]=[]
    for x in X:
        bestmukey = min([(i[0], np.linalg.norm(x[1]-mu[i[0]])) \
                    for i in enumerate(mu)], key=lambda t:t[1])[0]
        try:
            clusters[bestmukey].append(x)
        except KeyError:
            clusters[bestmukey] = [x]
    return clusters

def reevaluate_centers(mu, clusters):
    newmu = []
    keys = sorted(clusters.keys())
    for k in keys:
        newmu.append(vec_mean(clusters[k]))
    return newmu

def vec_mean(cluster, dim = 64):
    try:
        sum=[]
        for vector in cluster:
            if(len(sum)==0):
                sum = vector[1]
            else:
                for i in range(0, dim):
                    sum[i]=sum[i]+ vector[1][i]
        for i in range(0, dim):
            sum[i] = sum[i]/len(cluster)
    except IndexError:
        for i in range(0, dim):
            sum.append(0)
    return(sum)

def has_converged(mu, oldmu):
    return (set([tuple(a) for a in mu]) == set([tuple(a) for a in oldmu]))

def find_centers(X, K):
    # Initialize to K random centers
    dim = 64
    oldmu = random_centers(K, dim)
    mu = random_centers(K, dim)
    while not has_converged(mu, oldmu):
        oldmu = mu
        # Assign all points in X to clusters
        clusters = cluster_points(X, mu)
        # Reevaluate centers
        mu = reevaluate_centers(oldmu, clusters)
    return(mu, clusters)

trainingset=[]
direction = "/Users/Thomartin/mopsi/images/tour_eiffel"
surf = cv2.xfeatures2d.SURF_create()
trainingset = []
for file in os.listdir(direction):
    img = cv2.imread(direction+"/"+file)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    (kps,descs) = surf.detectAndCompute(gray, None)
    for j in range(0,len(descs)):
        trainingset.append((kps[j],descs[j],direction+"/"+file))

print(type(trainingset[4][1].tolist()[1]))
cen = random_centers(4, 64)
clus = cluster_points(trainingset, cen)
# print(reevaluate_centers(cen, clus ))
# print(cen)
# print(clus.keys())
set


import os
import requests
import json
from .exception import *

class HSRequest(object):
    ''' Object to handle HTTP requests

    Although we have greate requests package which can handle the HTTP request
    beautifully, we need this class to fit better our need like sending the
    requests with authentication information, download files, check HTTP
    errors...

    Attributes:
        DEFAULT_ENCODING (str): Default encoding for requests
        USER_AGENT (str): HTTP User agent used when sending requests
        parameters (dict): Some parameters for GET requests
        headers (dict): Custome headers for every requests
        http_status_code (int): HTTP status code returned of requests

    '''

    DEFAULT_ENCODING = "UTF-8"
    USER_AGENT = "HelloSign Python SDK"

    parameters = None
    headers = { 'User-Agent': USER_AGENT }
    http_status_code = 0
    verify_ssl = True

    def __init__(self, auth, env="production"):
        self.auth = auth
        self.env = env
        self.debug = (self.env != 'production')
        self.verify_ssl = (not self.debug)

    def _get_json_response(self, resp):
        ''' Parse a JSON response '''
        if resp is not None and resp.text is not None:
            return json.loads(resp.text)

    def get(self, url, headers=None, parameters=None, get_json=True):
        ''' Send a GET request with custome headers and parameters

        Args:
            url (str): URL to send the request to
            headers (str, optional): custom headers
            parameters (str, optional): optional parameters

        Returns:
            A JSON object of the returned response if `get_json` is True,
            Requests' response object otherwise

        '''

        if self.debug:
            print("GET: %s, headers=%s" % (url, headers))

        get_headers = self.headers
        get_parameters = self.parameters
        if get_parameters is None:
            # In case self.parameters is still empty
            get_parameters = {}
        if headers is not None:
            get_headers.update(headers)
        if parameters is not None:
            get_parameters.update(parameters)

        response = requests.get(url, headers=get_headers, params=get_parameters, auth=self.auth, verify=self.verify_ssl)
        self.http_status_code = response.status_code
        self._check_error(response)
        if get_json is True:
            return self._get_json_response(response)
        return response

    def get_file(self, url, filename, headers=None):
        ''' Get a file from a url and save it as `filename`

        Args:
            url (str): URL to send the request to

            filename (str): File name to save the file as, this can be either
                a full path or a relative path

            headers (str, optional): custom headers

        Returns:
            True if file is downloaded and written successfully, False
            otherwise.

        '''

        if self.debug:
            print("GET FILE: %s, headers=%s" % (url, headers))

        get_headers = self.headers
        if headers is not None:
            get_headers.update(headers)

        response = requests.get(url, headers=get_headers, auth=self.auth, verify=self.verify_ssl)

        self.http_status_code = response.status_code
        try:
            self._check_error(response)
            fd = os.open(filename, os.O_CREAT | os.O_RDWR)
            with os.fdopen(fd, "w+b") as f:
                f.write(response.content)
        except:
            return False

        return True

    def post(self, url, data=None, files=None, headers=None, get_json=True):
        ''' Make POST request to a url

        Args:
            url (str): URL to send the request to
            data (dict, optional): Data to send
            files (dict, optional): Files to send with the request
            headers (str, optional): custom headers

        Returns:
            A JSON object of the returned response if `get_json` is True,
            Requests' response object otherwise

        '''

        if self.debug:
            print("POST: %s, headers=%s" % (url, headers))

        post_headers = self.headers
        if headers is not None:
            post_headers.update(headers)
        response = requests.post(url, headers=post_headers, data=data, auth=self.auth, files=files, verify=self.verify_ssl)
        self.http_status_code = response.status_code
        self._check_error(response)
        if get_json is True:
            return self._get_json_response(response)
        return response

    # TODO: use a expected key in returned json, if the returned key does not match, return false...
    def _check_error(self, response):
        ''' Check for HTTP error code from the response, raise exception if there's any

        Args:
            response (object): Object returned by requests' `get` and `post`
                methods

        Raises:
            HTTPError: If the status code of response is either 4xx or 5xx

        Returns:
            True if status code is not error code

        '''

        # If status code is 4xx or 5xx, that should be an error
        if response.status_code >= 400:
            j = self._get_json_response(response)
            err_cls = self._check_http_error_code(response.status_code)
            # I intended to return False here but raising a meaningful exception
            # may make senses more.
            try:
                raise err_cls("%s error: %s" % (response.status_code, j["error"]["error_msg"]), response.status_code)
            # This is to catch error when we post get oath data
            except TypeError:
                raise err_cls("%s error: %s" % (response.status_code, j["error_description"]), response.status_code)
        # Return True if everything looks OK
        return True

    def _check_http_error_code(self, code):
        return {
            400: BadRequest,
            401: Unauthorized,
            402: PaymentRequired,
            403: Forbidden,
            404: NotFound,
            405: MethodNotAllowed,
            406: NotAcceptable,
            408: RequestTimeout,
            409: Conflict,
            410: Gone,
            414: RequestURITooLong,
            415: UnsupportedMediaType,
            416: RequestedRangeNotSatisfiable,
            500: InternalServerError,
            501: MethodNotImplemented,
            502: BadGateway,
            503: ServiceUnavailable,
            504: GatewayTimeout
        }.get(code, HTTPError)


import csv
import json
import os
from utils.constants import Constants

def filter_synset_file():
    all_synsets_path = Constants.DATA_FOLDER + '/imagenet_synset_to_human_label_map.txt'
    used_synsets = Constants.DATA_FOLDER + '/thesis_synsets.txt'
    with open(all_synsets_path, 'r') as all_synsets_file:
        with open(used_synsets, 'r') as used_synsets_file:
            all_synsets = all_synsets_file.readlines()
            all_synsets = [s.strip('\n') for s in all_synsets]
            used_synsets = used_synsets_file.readlines()
            used_synsets = [s.strip('\n') for s in used_synsets]
    all_synsets_dict = {}
    for s in all_synsets:
        s_split = s.split('\t')
        all_synsets_dict[s_split[0]] = s_split[1]
    string = ""
    for s in used_synsets:
        descr = all_synsets_dict[s]
        string += s + ' ' + descr + '\n'
    with open(Constants.DATA_FOLDER + '/thesis_synsets_descr.txt', 'w') as text_file:
         text_file.write(string)

def synset_labels_dict():
    file_path = os.path.join(Constants.DATA_FOLDER, 'synsets-labels.txt')
    with open(file_path, 'r') as f:
        l = f.readlines()
    d = {}
    for i, li in enumerate(l):
        li = li.strip('\n')
        li = li.split(' ')[0]
        d[li] = i
    with open(os.path.join(Constants.DATA_FOLDER, 'synset_labels_dict.json'), 'w') as f:
        json.dump(d, f, indent=2)

def labels_synset_dict():
    file_path = os.path.join(Constants.DATA_FOLDER, 'synsets-labels.txt')
    with open(file_path, 'r') as f:
        l = f.readlines()
    d = {}
    for i, li in enumerate(l):
        li = li.strip('\n')
        li = li.split(' ')[0]
        d[i] = li
    with open(os.path.join(Constants.DATA_FOLDER, 'labels_synset_dict.json'), 'w') as f:
        json.dump(d, f, indent=2)

if __name__ == '__main__':
    synset_labels_dict()
    labels_synset_dict()
    filter_synset_file()


from collections import deque

def open(door):        # 열 수 있는 key가 있는지 확인
    if chr(ord(door) + 32) in keys:
        return True
    else:
        return False

def bfs(x, y):          # 현재 노드 주위를 탐색
    que = deque()
    que.append([x, y])
    while que:
        x, y = que.popleft()
        for nxt in range(4):
            nx = x + dx[nxt]
            ny = y + dy[nxt]
            if 0 <= nx < h and 0 <= ny < w and go(nx, ny):
                que.append([nx, ny])

def go(x, y):       # 갈 수 있으면 가고 True 리턴, 아니면 안 가고 False 리턴
    global cnt
    if visited[x][y]:                   # 이미 방문했으면 갈 수 없다.
        return False
    elif arr[x][y] == '.':                # 빈 공간을 만나면 갈 수 있다.
        visited[x][y] = 1
        return True
    elif arr[x][y] == '*':              # 벽을 만나면 갈 수 없다.
        return False
    elif 'a' <= arr[x][y] <= 'z':       # 열쇠를 주웠을 때
        keys.append(arr[x][y])          # 열쇠 추가
        visited[x][y] = 1
        return True
    elif 'A' <= arr[x][y] <= 'Z':       # 문을 마주쳤을 때
        if open(arr[x][y]):             # 열 수 있는지 확인
            visited[x][y] = 1
            return True
        else:
            doors.append([x, y])     # 열 수 없으면 열지 못한 문에 추가
            return False
    else:
        cnt += 1                        # 문서를 만났을 때 + 1
        visited[x][y] = 1               # 방문 표시
        return True

dx, dy = [0, 1, 0, -1], [1, 0, -1, 0]
n = int(input())
for _ in range(n):
    h, w = map(int, input().split())    # 지도의 높이 h, 너비 w
    arr = [input() for _ in range(h)]   # 지도
    keys = list(input())                # 소지하고 있는 키들
    doors = deque()      # 열지 못한 문의 좌표를 큐에 담는다 : [x, y]
    visited = [[0] * w for _ in range(h)]   # 방문 표시
    cnt = 0     # 획득한 문서의 수

    # 건물 가장자리 탐색
    for i in range(h):
        if i == 0 or i == h - 1:    # 첫 행과 마지막 행은 전부 다 탐색
            for j in range(w):
                if go(i, j):
                    bfs(i, j)
        else:                       # 나머지 행은 양 끝만 탐색
            if go(i, 0):
                bfs(i, 0)
            if go(i, w - 1):
                bfs(i, w - 1)

    while doors:                    # 열지 못했던 문들을 탐색
        change = 0
        sz = len(doors)
        for _ in range(sz):
            x, y = doors.popleft()
            if go(x, y):            # 문을 열 수 있는지 확인하고 이동
                bfs(x, y)
                change = 1
            else:
                doors.append([x, y])
        if not change:              # 더 열었던 문이 있을 때만!
            break

    print(cnt)


import numpy as np
import pandas as pd
from sklearn.metrics import mean_absolute_error
import matplotlib.pyplot as plt
pd.options.mode.chained_assignment = None
from datetime import datetime

# Load test data
test = np.load("test2020.npy")
test = test.reshape(test.shape[0]*test.shape[1])

# Load NN univariate o multivariate
pred_cnn = np.load("mmcnn.npy")
pred_cnn = pred_cnn.reshape(pred_cnn.shape[0]*pred_cnn.shape[1])

pred_rnn = np.load("mmrnn.npy")
pred_rnn = pred_rnn.reshape(pred_rnn.shape[0]*pred_rnn.shape[1])

pred_crnn = np.load("mmcnnandrnn.npy")
pred_crnn = pred_crnn.reshape(pred_crnn.shape[0]*pred_crnn.shape[1])

# Load ARIMA or TFM
pred_arima = pd.read_csv("ARIMA_FINAL.csv")
pred_arima = pred_arima.to_numpy()
pred_arima = pred_arima.transpose()
pred_arima = pred_arima.reshape(pred_arima.shape[0]*pred_arima.shape[1],)

#### CREATE DATABASE FOR TABLES

#MAE
mae_cnn = mean_absolute_error(test, pred_cnn)
mae_rnn = mean_absolute_error(test, pred_rnn)
mae_arima = mean_absolute_error(test, pred_arima)
mae_crnn = mean_absolute_error(test, pred_crnn)

#RMSE
def rmse(predictions):
    rmse = np.sqrt(sum((test-predictions)**2)  / len(test))
    return rmse

rmse_cnn = rmse(pred_cnn)
rmse_rnn = rmse(pred_rnn)
rmse_arima = rmse(pred_arima)
rmse_crnn = rmse(pred_crnn)

#MAPE
def mape(predictions):
    mape = np.mean(np.abs((test - predictions)/test))*100
    return mape

mape_cnn = mape(pred_cnn)
mape_rnn = mape(pred_rnn)
mape_arima = mape(pred_arima)
mape_crnn = mape(pred_crnn)

# Create dataframe

df_error=pd.DataFrame(data={"RMSE": [rmse_arima, rmse_cnn, rmse_rnn, rmse_crnn],
                            "MAE": [mae_arima, mae_cnn, mae_rnn, mae_crnn],
                            "MAPE": [mape_arima, mape_cnn, mape_rnn, mape_crnn]}, index = ["ARIMA", "CNN", "RNN", "CNNandRNN"])

#### CREATE DATABASE FOR BARPLOTS

# Database. Columns: Error, day, hour, month
def data_base(error):
    df1=pd.read_csv("precios_14_20.txt", sep=",", index_col=0)
    df=df1[-8784:]
    error = error.tolist()
    df["error"]=error
    df=df.drop("price", axis = 1)
    index = df.index
    day = list()
    hour = list()
    month = list()
    for i in index:
        day.append(i[0:10])
        hour.append(i[11:13])
        month.append(i[5:7])
    day_dt = [datetime.strptime(x, '%Y-%m-%d') for x in day]
    weekday = [x.weekday() for x in day_dt]
    df["day"] = weekday
    df["hour"] = hour
    df["month"] = month
    return df

# MSE for each of the hours
def mse_hours(predictions):
    mse = (test- predictions)**2
    return mse

mse_hours_cnn =   mse_hours(pred_cnn)
mse_hours_rnn =   mse_hours(pred_rnn)
mse_hours_arima = mse_hours(pred_arima)
mse_hours_crnn =  mse_hours(pred_crnn)

df_cnn = data_base(mse_hours_cnn)
df_rnn = data_base(mse_hours_rnn)
df_arima = data_base(mse_hours_arima)
df_crnn = data_base(mse_hours_crnn)

# Group data by day, hour and month. Output: RMSE per day, hour and month
def group_data(df):
    day_error=df.groupby(["day"])["error"].mean()
    hour_error=df.groupby(["hour"])["error"].mean()
    month_error=df.groupby(["month"])["error"].mean()
    day_error = day_error.tolist()
    hour_error = hour_error.tolist()
    month_error = month_error.tolist()
    return np.sqrt(day_error), np.sqrt(hour_error), np.sqrt(month_error)

day_cnn, hour_cnn, month_cnn = group_data(df_cnn)
day_ARIMA, hour_ARIMA, month_ARIMA = group_data(df_arima)
day_rnn, hour_rnn, month_rnn = group_data(df_rnn)
day_crnn, hour_crnn, month_crnn = group_data(df_crnn)

# Hours NEURAL NETWORKS
x = np.arange(24)
width = 0.20
x_labels = ["00", "01", "02","03", "04", "05", "06","07", "08", "09","10","11","12","13","14","15","16","17","18","19",
      "20","21","22","23"]

plt.bar(x -0.2, hour_cnn, width, color = "SkyBlue" , edgecolor="black")
plt.bar(x , hour_rnn, width, edgecolor="black", color = "IndianRed")
plt.bar(x + 0.2 , hour_crnn, width, edgecolor="black", color = "forestgreen")
plt.title("RMSE per hours")
plt.ylabel("RMSE")
plt.xticks(x, x_labels, rotation=0)
plt.legend(["CNN", "RNN", "CNN+RNN"])
plt.show()

# Hours NN VS ARIMA
x = np.arange(24)
width = 0.40
x_labels = ["00", "01", "02","03", "04", "05", "06","07", "08", "09","10","11","12","13","14","15","16","17","18","19",
      "20","21","22","23"]

plt.bar(x - 0.2, hour_cnn, width, color = "SkyBlue" , edgecolor="black")
plt.bar(x + 0.2, hour_ARIMA, width, color = "IndianRed", edgecolor="black")
plt.title("RMSE per hours")
plt.ylabel("RMSE")
plt.xticks(x, x_labels, rotation=0)
plt.legend(["CNN", "ARIMA"])
plt.show()

### Days
x = np.arange(7)
width = 0.40
x_labels = ["Monday", "Tuesday", "Wednesday", "Thrusday", "Friday", "Saturday", "Sunday"]

plt.bar(x - 0.2, day_cnn, width, color = "SkyBlue" , edgecolor="black")
plt.bar(x + 0.2, day_ARIMA, width, color = "IndianRed", edgecolor="black")
plt.title("RMSE per days")
plt.ylabel("RMSE")
plt.xticks(x, x_labels, rotation=45)
plt.legend(["CNN", "ARIMA"])
plt.show()

### Months
x = np.arange(12)
width = 0.40
x_labels = ["January","February","March","April","May","June","July","August","September","October","November",
            "December"]
plt.bar(x - 0.2, month_cnn, width, color = "SkyBlue" , edgecolor="black")
plt.bar(x + 0.2, month_ARIMA, width, color = "IndianRed", edgecolor="black")
plt.title("RMSE per months")
plt.ylabel("RMSE")
plt.xticks(x, x_labels, rotation=45)
plt.legend(["CNN", "ARIMA"])
plt.show()


import re
import sys
from typing import Any, Dict, List, Optional, Sequence, TextIO, Tuple, cast

import click
import koji
from bugzilla import Bugzilla
from bugzilla.bug import Bug
from jira import JIRA, Issue
from tenacity import retry, stop_after_attempt

from elliottlib import Runtime, brew
from elliottlib.assembly import AssemblyTypes
from elliottlib.cli.common import cli, click_coroutine
from elliottlib.config_model import KernelBugSweepConfig
from elliottlib.exceptions import ElliottFatalError
from elliottlib.util import green_print
from elliottlib.bzutil import JIRABugTracker

@retry(reraise=True, stop=stop_after_attempt(3))
def _search_issues(jira_client, *args, **kwargs):
    return jira_client.search_issues(*args, **kwargs)

class FindBugsKernelCli:
    def __init__(self, runtime: Runtime, trackers: Sequence[str],
                 clone: bool, reconcile: bool, comment: bool, dry_run: bool):
        self._runtime = runtime
        self._logger = runtime.logger
        self.trackers = list(trackers)
        self.clone = clone
        self.reconcile = reconcile
        self.comment = comment
        self.dry_run = dry_run
        self._id_bugs: Dict[int, Bug] = {}  # cache for kernel bug; key is bug_id, value is Bug object
        self._tracker_map: Dict[int, Issue] = {}  # bug_id -> KMAINT jira mapping

    async def run(self):
        logger = self._logger
        if self.reconcile and not self.clone:
            raise ElliottFatalError("--reconcile must be used with --clone")
        if self._runtime.assembly_type is not AssemblyTypes.STREAM:
            raise ElliottFatalError("This command only supports stream assembly")
        group_config = self._runtime.group_config
        raw_config = self._runtime.gitdata.load_data(key='bug', replace_vars=group_config.vars).data.get("kernel_bug_sweep")
        if not raw_config:
            logger.warning("kernel_bug_sweep is not defined in bug.yml")
            return
        config = KernelBugSweepConfig.parse_obj(raw_config)
        jira_tracker = self._runtime.get_bug_tracker("jira")
        jira_client: JIRA = jira_tracker._client
        bz_tracker = self._runtime.get_bug_tracker("bugzilla")
        bz_client: Bugzilla = bz_tracker._client
        koji_api = self._runtime.build_retrying_koji_client(caching=True)

        # Getting KMAINT trackers
        trackers_keys = self.trackers
        trackers: List[Issue] = []
        if not trackers_keys:
            logger.info("Searching for open trackers...")
            trackers = self._find_kmaint_trackers(jira_client, config.tracker_jira.project, config.tracker_jira.labels)
            trackers_keys = [t.key for t in trackers]
            logger.info("Found %s tracker(s): %s", len(trackers_keys), trackers_keys)
        else:
            logger.info("Find kernel bugs linked from KMAINT tracker(s): %s", trackers_keys)
            for key in trackers_keys:
                logger.info("Getting tracker JIRA %s...", key)
                tracker = jira_client.issue(key)
                trackers.append(tracker)

        # Get kernel bugs linked from KMAINT trackers
        report: Dict[str, Any] = {"kernel_bugs": []}
        for tracker in trackers:
            bugs = self._find_bugs(jira_client, tracker, bz_client, config.bugzilla.target_releases)
            bug_ids = {int(b.id) for b in bugs}
            logger.info("Found %s bug(s) from %s: %s", len(bugs), tracker, bug_ids)
            for bug_id, bug in zip(bug_ids, bugs):
                if bug_id in self._tracker_map and self._tracker_map[bug_id].key != tracker.key:
                    raise ValueError(f"Bug {bug_id} is linked in multiple KMAINT trackers: {tracker.key} {self._tracker_map[bug_id].key}")
                self._id_bugs[bug_id] = bug
                self._tracker_map[bug_id] = tracker
                report["kernel_bugs"].append({
                    "id": bug_id,
                    "status": bug.status,
                    "summary": bug.summary,
                    "tracker": tracker,
                })
            if self.comment:
                logger.info("Checking if making a comment on tracker %s is needed...", tracker.key)
                self._comment_on_tracker(jira_client, tracker, koji_api, config.target_jira)

        if self.clone and self._id_bugs:
            # Clone kernel bugs into OCP Jira
            logger.info("Cloning bugs...")
            cloned_issues = self._clone_bugs(jira_client, list(self._id_bugs.values()), config.target_jira)
            report["clones"] = {}
            for bug_id, issues in cloned_issues.items():
                report["clones"][bug_id] = sorted(issue.key for issue in issues)
            logger.info("Done.")

        # Print a report
        self._print_report(report, sys.stdout)

    @staticmethod
    def _find_kmaint_trackers(jira_client: JIRA, tracker_project: str, labels: List[str]):
        conditions = [
            f"project = {tracker_project}",
            "status != Closed",
        ]
        if labels:
            conditions.extend([f"labels = \"{label}\"" for label in labels])
        jql = f'{" AND ".join(conditions)} ORDER BY created DESC'
        # 50 most recently created KMAINT trackers should be more than enough
        matched_issues = _search_issues(jira_client, jql, maxResults=50)
        return cast(List[Issue], matched_issues)

    def _find_bugs(self, jira_client: JIRA, tracker: Issue, bz_client: Bugzilla, bz_target_releases: Sequence[str]):
        logger = self._logger
        logger.info("Searching bugs in JIRA %s...", tracker.key)
        links = jira_client.remote_links(tracker.key)
        # Search for kernel bugs in tracker content
        pattern = re.compile(r"(?:bugzilla.redhat.com/|bugzilla.redhat.com/show_bug.cgi\?id=|bz)(\d+)")
        content = f"{tracker.fields.summary}\n{tracker.fields.description}"
        for link in links:
            content += f"\n{link.object.title}\n{link.object.url}"
        m = pattern.findall(content)
        bug_ids = sorted(set(map(int, m)))
        if not bug_ids:
            logger.info("No bugs found from %s", tracker.key)
            return []
        filtered_bugs = self._get_and_filter_bugs(bz_client, bug_ids, bz_target_releases)
        return filtered_bugs

    def _get_and_filter_bugs(self, bz_client: Bugzilla, bug_ids: List[int], bz_target_releases: Sequence[str]):
        """ Get specified bugs from Bugzilla, then return those bugs that match the defined target release.
        """
        logger = self._logger
        filtered_bugs: List[Bug] = []
        logger.info("Getting bugs %s from Bugzilla...", bug_ids)
        bugs = cast(List[Optional[Bug]], bz_client.getbugs(bug_ids))
        target_releases = set(bz_target_releases)
        for bug_id, bug in zip(bug_ids, bugs):
            if not bug:
                raise IOError(f"Error getting bug {bug_id}")
            target_release = bug.cf_zstream_target_release
            if not target_release:
                logger.warning("Target release of bug %s is not set", bug.weburl)
                continue
            if target_release not in target_releases:
                logger.warning("Bug %s is skipped because target release \"%s\" is not listed", bug.weburl, target_release)
                continue
            logger.info("Found bug %s matching target release %s", bug_id, target_release)
            filtered_bugs.append(bug)
        return filtered_bugs

    def _clone_bugs(self, jira_client: JIRA, bugs: Sequence[Bug], conf: KernelBugSweepConfig.TargetJiraConfig):
        logger = self._logger
        ocp_target_release = conf.target_release
        result: Dict[int, List[Issue]] = {}  # key is bug_id, value is a list of cloned jiras
        for bug in bugs:
            bug_id = int(bug.id)
            kmaint_tracker = self._tracker_map.get(bug_id)
            kmaint_tracker_key = kmaint_tracker.key if kmaint_tracker else None
            logger.info("Checking if %s was already cloned to OCP %s...", bug_id, ocp_target_release)
            jql_str = f'project = {conf.project} and component = {conf.component} and labels = art:cloned-kernel-bug and labels = "art:bz#{bug_id}" and "Target Version" = "{ocp_target_release}" order by created DESC'
            found_issues = cast(List[Issue], _search_issues(jira_client, jql_str=jql_str))
            if not found_issues:  # this bug is not already cloned into OCP Jira
                logger.info("Creating JIRA for bug %s...", bug.weburl)
                fields = self._new_jira_fields_from_bug(bug, ocp_target_release, kmaint_tracker_key, conf)
                if not self.dry_run:
                    issue = jira_client.create_issue(fields)
                    jira_client.add_remote_link(issue.key, {"title": f"BZ{bug_id}", "url": bug.weburl})
                    if kmaint_tracker:
                        jira_client.create_issue_link("Blocks", issue.key, kmaint_tracker)
                    result[bug_id] = [issue]
                else:
                    logger.warning("[DRY RUN] Would have created Jira for bug %s", bug_id)
            else:  # this bug is already cloned into OCP Jira
                logger.info("Bug %s is already cloned into OCP: %s", bug_id, [issue.key for issue in found_issues])
                result[bug_id] = found_issues
                if not self.reconcile:
                    continue
                fields = self._new_jira_fields_from_bug(bug, ocp_target_release, kmaint_tracker_key, conf)
                for issue in found_issues:
                    if issue.fields.status.name.lower() == "closed":
                        logger.info("No need to reconcile %s because it is Closed.", issue.key)
                        continue
                    logger.info("Reconciling Jira %s (cloned from bug %s) for %s", issue.key, bug_id, ocp_target_release)
                    if not self.dry_run:
                        issue.update(fields)
                    else:
                        logger.warning("[DRY RUN] Would have updated Jira %s to match bug %s", issue.key, bug_id)

        return result

    @staticmethod
    def _print_report(report: Dict, out: TextIO):
        print_func = green_print if out.isatty() else print  # use green_print if out is a TTY
        bugs = sorted(report.get("kernel_bugs", []), key=lambda bug: bug["id"])
        clones = report.get("clones", {})
        for bug in bugs:
            cloned_issues = clones.get(bug['id'], [])
            text = f"{bug['tracker']}\t{bug['id']}\t{'N/A' if not cloned_issues else ','.join(cloned_issues)}\t{bug['status']}\t{bug['summary']}"
            print_func(text, file=out)

    def _comment_on_tracker(self, jira_client: JIRA, tracker: Issue, koji_api: koji.ClientSession,
                            conf: KernelBugSweepConfig.TargetJiraConfig):
        logger = self._runtime.logger
        # Determine which NVRs have the fix. e.g. ["kernel-5.14.0-284.14.1.el9_2"]
        nvrs = re.findall(r"(kernel(?:-rt)?-\S+-\S+)", tracker.fields.summary)
        if not nvrs:
            raise ValueError("Couldn't determine build NVRs for tracker %s", tracker.key)
        nvrs = sorted(nvrs)
        # Check if nvrs are already tagged into OCP
        logger.info("Getting Brew tags for build(s) %s...", nvrs)
        candidate_brew_tag = conf.candidate_brew_tag
        prod_brew_tag = conf.prod_brew_tag
        build_tags = brew.get_builds_tags(nvrs, koji_api)
        shipped = all([any(map(lambda t: t["name"] == prod_brew_tag, tags)) for tags in build_tags])
        modified = all([any(map(lambda t: t["name"] == candidate_brew_tag, tags)) for tags in build_tags])
        tracker_message = None
        if shipped:
            tracker_message = f"Build(s) {nvrs} was/were already shipped and tagged into {prod_brew_tag}."
        elif modified:
            tracker_message = f"Build(s) {nvrs} was/were already tagged into {candidate_brew_tag}."
        if not tracker_message:
            logger.info("No need to make a comment on %s", tracker.key)
            return
        comments = jira_client.comments(tracker.key)
        if any(map(lambda comment: comment.body == tracker_message, comments)):
            logger.info("A comment was already made on %s", tracker.key)
            return
        logger.info("Making a comment on tracker %s", tracker.key)
        if not self.dry_run:
            jira_client.add_comment(tracker.key, tracker_message)
            logger.info("Left a comment on tracker %s", tracker.key)
        else:
            logger.warning("[DRY RUN] Would have left a comment on tracker %s", tracker.key)

    @staticmethod
    def _new_jira_fields_from_bug(bug: Bug, ocp_target_version: str, kmaint_tracker: Optional[str], conf: KernelBugSweepConfig.TargetJiraConfig):
        summary = f"{bug.summary} [rhocp-{ocp_target_version}]"
        if not summary.startswith("kernel"):  # ensure bug summary start with "kernel"
            summary = "kernel[-rt]: " + summary
        description = f"Cloned from {bug.weburl} by OpenShift ART Team:\n----\n{bug.description}"
        priority_mapping = {
            "urgent": "Critical",
            "high": "Major",
            "medium": "Normal",
            "low": "Minor",
            "unspecified": "Undefined",
        }
        bug_groups = set(bug.groups)
        fields = {
            "project": {"key": conf.project},
            "components": [{"name": conf.component}],
            "security": {'name': 'Red Hat Employee'} if 'private' in bug_groups or 'redhat' in bug_groups else None,
            "priority": {'name': priority_mapping.get(bug.priority, "Undefined")},
            "summary": summary,
            "description": description,
            "issuetype": {"name": "Bug"},
            "versions": [{"name": ocp_target_version[:ocp_target_version.rindex(".")]}],
            f"{JIRABugTracker.FIELD_TARGET_VERSION}": [{
                "name": ocp_target_version,
            }],
            "labels": ["art:cloned-kernel-bug", f"art:bz#{bug.id}"],
        }
        if kmaint_tracker:
            fields["labels"].append(f"art:kmaint:{kmaint_tracker}")

        # TODO: The following lines are commented out because we haven't reached to agreement
        # on how to handle kernel CVEs in OCP at this moment.
        # Without the following lines, kernel CVEs will be copied as normal (non-CVE) bugs.

        # is_cve_tracker = set(constants.TRACKER_BUG_KEYWORDS).issubset(set(bug.keywords))
        # if is_cve_tracker:
        #     # Find flaw bugs associated with the CVE tracker
        #     cve_flaws = []
        #     for flaw_id, flaw_bug in zip(bug.blocks, bug.bugzilla.getbugs(bug.blocks)):
        #         if not flaw_bug:
        #             raise IOError(f"Error getting flaw bug {flaw_id}. Permission issue?")
        #         if not BugzillaBug(flaw_bug).is_flaw_bug():
        #             continue  # this is not a flaw bug
        #         cve_flaws.append(flaw_bug)
        #     labels = {"Security", "SecurityTracking"}
        #     cve_names = re.findall(r"(CVE-\d+-\d+)", bug.summary)
        #     labels |= set(cve_names)
        #     labels |= {f"pscomponent:{component}" for component in bug.components}
        #     labels |= {f"flaw:bz#{flaw.id}" for flaw in cve_flaws}
        #     fields["labels"] += sorted(labels)
        return fields

@cli.command("find-bugs:kernel", short_help="Find kernel bugs")
@click.option("--tracker", "trackers", metavar='JIRA_KEY', multiple=True,
              help="Find by the specified KMAINT tracker JIRA_KEY")
@click.option("--clone",
              is_flag=True,
              default=False,
              help="Clone kernel bugs into OCP Jira")
@click.option("--reconcile",
              is_flag=True,
              default=False,
              help="Update summary, description, etc for already cloned Jira bugs. Must be used with --clone")
@click.option("--comment",
              is_flag=True,
              default=False,
              help="Make comments on KMAINT trackers")
@click.option("--dry-run",
              is_flag=True,
              default=False,
              help="Don't change anything")
@click.pass_obj
@click_coroutine
async def find_bugs_kernel_cli(
        runtime: Runtime, trackers: Tuple[str, ...], clone: bool,
        reconcile: bool, comment: bool, dry_run: bool):
    """Find kernel bugs in Bugzilla for weekly kernel release through OCP.

    Example 1: Find kernel bugs and print them out
    \b
        $ elliott -g openshift-4.14 find-bugs:kernel

    Example 2: Find kernel bugs and clone them into OCP Jira
    \b
        $ elliott -g openshift-4.14 find-bugs:kernel --clone

    Example 3: Clone kernel bugs into OCP Jira and also update already cloned Jiras
    \b
        $ elliott -g openshift-4.14 find-bugs:kernel --clone --reconcile
    """
    runtime.initialize(mode="none")
    cli = FindBugsKernelCli(
        runtime=runtime,
        trackers=trackers,
        clone=clone,
        reconcile=reconcile,
        comment=comment,
        dry_run=dry_run
    )
    await cli.run()


from outputs_fromDrone import InitializeConnectDrone, ReturnDroneAngle

from input_forDrone import droneArm, droneTakeOff, condition_yaw, send_global_velocity, send_ned_velocity_heading, goto_position_target_local_ned
from drone_variousMovements import fixDistanceToBlade,moveToNewLocation, moveDroneInLocalCoord, moveToNewDistance

import time
import math
import numpy
from dronekit import VehicleMode

import serial

import json

safeDistance = 2000

distDroneToBlade = 2500

## Initialize connection to drone
vehicle = InitializeConnectDrone()

print("Arm the drone...")
## Arm drone
droneArm(vehicle)

print("Drone take off...")
## Drone take off - test take of to 10 meters
droneTakeOff(10, vehicle)

##moveToNewDistance(vehicle, 331,320)
##
##time.sleep(5)
##
##print("slept")

## move drone using velocity from given distance
def movementToDistancePosition(distX, distY):
    stopper = False

    ## x is +forward, -backward, y is +right, -left

    signX = numpy.sign(distX)
    signY = numpy.sign(distY)
    counterX = abs(distX)
    counterY = abs(distY)
    while stopper is False:

        if counterX > 0:
            xMove = 1
            counterX-=0.5
        else:
            xMove = 0

        if counterY > 0:
            yMove = 1
            counterY-=0.5
        else:
            yMove = 0

        if yMove == 0 and xMove == 0:
            stopper = True

        moveDroneInLocalCoord(vehicle, [signX*xMove,signY*yMove,0], [0.5,0.5,0.5])
        time.sleep(0.1)

## move drone using velocity and given position
def movementToPositionNEW(posX, posY):
    stopper = False

    ## x is +forward, -backward, y is +right, -left
    distX = posX - vehicle.location.local_frame.north
    distY = posY - vehicle.location.local_frame.east

    signX = numpy.sign(distX)
    signY = numpy.sign(distY)

    while True:
        moveDroneInLocalCoord(vehicle, [distX,distY,0], [1,1,1])
        if math.fabs(vehicle.location.local_frame.north) >= math.fabs(posX*0.95) and math.fabs(vehicle.location.local_frame.east) >= math.fabs(posY*0.95):
            print("Reached")
            break

##        time.sleep(1)

def getDataFromServer(sock):

    if sock.inWaiting():

        receiveMsg = sock.readline()

        try:

            unpickledDataFull = json.loads(receiveMsg.strip().decode())

            outputArr = numpy.array(unpickledDataFull)

            sock.write('4Send'.encode())

#            print(unpickledDataFull)

            return outputArr
        except json.JSONDecodeError:
            sock.write('4Send'.encode())
            print("error")

    return -1

serialReceive = serial.Serial('COM15', 115200, timeout = 10)

print("start waiting for data...")
try:
    while True:
        sendData = getDataFromServer(serialReceive)

        if sendData is not -1:

            for i in range(0,len(sendData)):
                print(sendData[i,:])

                xPosNew = float(sendData[i,1])

                yPosNew = float(sendData[i,0])
##                while True:

##                    send_ned_velocity_heading(1/sendData[i,1], 1/sendData[i,0], 0, vehicle)

                while True:

                        distToTravel = math.sqrt((xPosNew - float(vehicle.location.local_frame.north))**2 + (yPosNew - float(vehicle.location.local_frame.east))**2)

                        velX = (0.5/distToTravel)*(xPosNew - float(vehicle.location.local_frame.north))
                        velY = (0.5/distToTravel)*(yPosNew - float(vehicle.location.local_frame.east))
                        send_ned_velocity_heading(velX, velY, 0, vehicle)
                        print(vehicle.location.local_frame.north)
                        if math.fabs(float(vehicle.location.local_frame.north)) >= math.fabs(xPosNew*0.95) and math.fabs(float(vehicle.location.local_frame.east)) >= math.fabs(yPosNew*0.95):
                            print("Reached")
                            break
                        time.sleep(1)
##                movementToDistancePosition(sendData[i,1], sendData[i,0])
##                time.sleep(1)

except KeyboardInterrupt:
    print("exit")

##movementToDistancePosition(-1, -5)
##
##time.sleep(1)
##
##movementToDistancePosition(1, -4)
##
##time.sleep(1)
##
##movementToDistancePosition(3, -2)
##
##time.sleep(1)
##
##movementToDistancePosition(5, 0)
##
##time.sleep(1)
##
##movementToDistancePosition(4, 2)
##
##time.sleep(1)

##Rotate the drone and add the angle to the heading of the drone
##print("rotate the drone ")
##print(math.degrees(vehicle.attitude.yaw))
##condition_yaw(45,vehicle,relative=True)
##
##send_global_velocity(0,0,0,vehicle)
##time.sleep(1)
##
##print(math.degrees(vehicle.attitude.yaw))

##time.sleep(1)
##
#### Move Drone in local Coord system
##for i in range(0,10):
##    moveDroneInLocalCoord(vehicle, [1,0,0], [1,0,0])
##
##    time.sleep(0.1)
##
##print(math.degrees(vehicle.attitude.yaw))

## Send command to drone
##print("Fly by velocity")
##for i in range(0,10):
##    moveDroneInLocalCoord(vehicle, [1,1,0], [2,2,2])

####    fixDistanceToBlade(safeDistance, distDroneToBlade, vehicle)
####    distDroneToBlade -=10
##    ##condition_yaw(meanAngle_compensated)
##    time.sleep(1)

print("Setting LAND mode...")
vehicle.mode = VehicleMode("LAND")

print ("Close vehicle object")
vehicle.close()

##sitl.stop()

print("Completed")


import os
from netCDF4 import Dataset
import numpy as np

here = os.path.dirname(os.path.abspath(__file__))
datadir = os.path.join(here, '../../data')
outdir = os.path.join(here, '../../output')

paramf = {'nh': os.path.join(datadir, 'paramfiles/inv_params_osi455_nh_200301-202012_1day.nc'),
          'sh': os.path.join(datadir, 'paramfiles/inv_params_osi455_sh_200208-202007_1day.nc')}

outfile = os.path.join(outdir, 'latex_stats_paramfiles.tex')

mondict = {0: 'Jan',
           1: 'Feb',
           2: 'Mar',
           3: 'Apr',
           4: 'May',
           5: 'Jun',
           6: 'Jul',
           7: 'Aug',
           8: 'Sep',
           9: 'Oct',
           10: 'Nov',
           11: 'Dec'}

def main():

    varlist = ['flags', 'absA_gapfill', 'ThetaA_gapfill', 'RMS_Res_real',
               'RMS_Res_imag', 'C_real_gapfill', 'C_imag_gapfill', 'lat', 'lon']
    stats = {}
    data = {}

    for hemi in ['nh', 'sh']:

        stats[hemi] = {}
        data[hemi] = {}

        with Dataset(paramf[hemi], 'r') as dataset:

            for var in varlist:
                data[hemi][var] = dataset.variables[var][:]

        # Finding data shape
        shx, shy = data['nh']['RMS_Res_real'][0, :, :].shape
        rmsdtype = data['nh']['RMS_Res_real'].dtype

        # Finding the per-month flags
        flagok = np.zeros((12, shx, shy), dtype=data[hemi]['flags'][:].dtype)
        for mon in range(12):
            flagok[mon, :, :] = data[hemi]['flags'][mon, :, :] == 0

        # Calculating the geostrophic speeds
        cdtype = np.double
        data[hemi]['C_gapfill'] = np.zeros((12, shx, shy), dtype=cdtype)

        # In addition to the other flagging, we want to flag any NaNs
        # in the geostropic currents
        flagokgeo = flagok.copy()
        for mon in range(12):
            flagokgeo[mon, :, :] = np.logical_and(flagok[mon, :, :], ~data[hemi]['C_real_gapfill'][mon, :, :].mask)
            flagokgeo[mon, :, :] = np.logical_and(flagok[mon, :, :], ~data[hemi]['C_imag_gapfill'][mon, :, :].mask)
        data[hemi]['C_real_gapfill'].mask = 0
        data[hemi]['C_imag_gapfill'].mask = 0

        for mon in range(12):
            # Set the gapfilled and sea/land areas to 0 to avoid nasty numbers
            data[hemi]['C_real_gapfill'][mon, :, :][flagokgeo[mon, :, :] == 0] = 0
            data[hemi]['C_imag_gapfill'][mon, :, :][flagokgeo[mon, :, :] == 0] = 0

            ccomb = np.zeros((2, shx, shy), dtype=cdtype)
            cc1 = data[hemi]['C_real_gapfill'][mon, :, :]
            ccomb[0, :, :] = cc1 * cc1
            cc2 =  data[hemi]['C_imag_gapfill'][mon, :, :]
            ccomb[1, :, :] = cc2 * cc2
            ccombsum = np.nansum(ccomb, axis=0)
            data[hemi]['C_gapfill'][mon, :, :] = np.sqrt(ccombsum)

        # Averaging the RMS var
        data[hemi]['RMS_Res'] = np.zeros((12, shx, shy), dtype=rmsdtype)
        for mon in range(12):
            rmsav = np.zeros((2, shx, shy), dtype=rmsdtype)
            rmsav[0, :, :] = data[hemi]['RMS_Res_real'][mon, :, :]
            rmsav[1, :, :] = data[hemi]['RMS_Res_real'][mon, :, :]
            data[hemi]['RMS_Res'][mon, :, :] = np.nanmean(rmsav, axis=0)

        for var in ['absA_gapfill', 'ThetaA_gapfill', 'RMS_Res', 'C_gapfill']:
            stats[hemi][var] = {}

            for mon in range(12):
                # Calculate the per-month stats where the flag shows
                # no gapfilling
                if var == 'C_gapfill':
                    field = data[hemi][var][mon, :, :][flagokgeo[mon, :, :] == 1]
                else:
                    field = data[hemi][var][mon, :, :][flagok[mon, :, :] == 1]
                stats[hemi][var][mon] = np.nanmean(field)
                # Changing the absA variables to percentage
                if var == 'absA_gapfill':
                    stats[hemi][var][mon] = 100. * stats[hemi][var][mon]

    # Write out the latex file
    with open(outfile, 'a+') as outf:

        outf.write("\\begin{table}[htb]\n")
        outf.write("\\begin{center}\n")
        outf.write("\\begin{tabular}{|l||c|c|c||c|c|c|}\n")
        outf.write("\hline\n")
        outf.write("{} & \multicolumn{3}{|c||}{Northern hemisphere} & \multicolumn{3}{|c|}{Southern hemisphere} \\\\ \n")
        outf.write("\hline\n")
        outf.write("Month & $\\langle|A|\\rangle$ & $\\langle\\theta \\rangle$ & $\\langle U_{wg} \\rangle$ & $\\langle|A|\\rangle$ & $\\langle\\theta\\rangle$ & $\\langle U_{wg} \\rangle$ \\\\ \n")
        outf.write("{} & / \\% & / degree & / ms$^{-1}$ & / \\% & / degree & / ms$^{-1}$ \\\\ \n")
        outf.write("\hline\n")

        for mon in range(12):
            outf.write("{} & {} & {} & {} & {} & {} & {} \\\\ \n".format(
                mondict[mon],
                "{:+.1f}".format(stats['nh']['absA_gapfill'][mon]),
                "{:+.1f}".format(stats['nh']['ThetaA_gapfill'][mon]),
                "{:+.3f}".format(stats['nh']['C_gapfill'][mon]),
                "{:+.1f}".format(stats['sh']['absA_gapfill'][mon]),
                "{:+.1f}".format(stats['sh']['ThetaA_gapfill'][mon]),
                "{:+.3f}".format(stats['sh']['C_gapfill'][mon])))
        outf.write("\hline\n")
        outf.write("\end{tabular}\n")
        outf.write("\end{center}\n")
        outf.write("\caption[Parameter statistics]{}\n")
        outf.write("\label{tab:stats:param}\n")
        outf.write("\end{table}\n")
        outf.write("\n\n")

#    # OLD VERSION WITH RMS ERRORS
#    # Write out the latex file
#    with open(outfile, 'a+') as outf:
#
#        outf.write("\\begin{table}[htb]\n")
#        outf.write("\\begin{center}\n")
#        outf.write("\\begin{tabular}{|l||c|c|c||c|c|c|}\n")
#        outf.write("\hline\n")
#        outf.write("{} & \multicolumn{3}{|c||}{Northern hemisphere} & \multicolumn{3}{|c|}{Southern hemisphere} \\\\ \n")
#        outf.write("\hline\n")
#        outf.write("Month & $\\langle|A|\\rangle$ & $\\langle\\theta \\rangle$ & $\\langle \\varepsilon(dX) + \\varepsilon(dY) \\rangle$ & $\\langle|A|\\rangle$ & $\\langle\\theta\\rangle$ & $\\langle \\varepsilon(dX) + \\varepsilon(dY) \\rangle$ \\\\ \n")
#        outf.write("{} & / \\% & / degree & / ms$^{-1}$ & / \\% & / degree & / ms$^{-1}$ \\\\ \n")
#        outf.write("\hline\n")
#
#        for mon in range(12):
#            outf.write("{} & {} & {} & {} & {} & {} & {} \\\\ \n".format(
#                mondict[mon],
#                "{:+.1f}".format(stats['nh']['absA_gapfill'][mon]),
#                "{:+.1f}".format(stats['nh']['ThetaA_gapfill'][mon]),
#                "{:+.3f}".format(stats['nh']['RMS_Res'][mon]),
#                "{:+.1f}".format(stats['sh']['absA_gapfill'][mon]),
#                "{:+.1f}".format(stats['sh']['ThetaA_gapfill'][mon]),
#                "{:+.3f}".format(stats['sh']['RMS_Res'][mon])))
#        outf.write("\hline\n")
#        outf.write("\end{tabular}\n")
#        outf.write("\end{center}\n")
#        outf.write("\caption[Parameter statistics]{}\n")
#        outf.write("\label{tab:stats:param}\n")
#        outf.write("\end{table}\n")
#        outf.write("\n\n")

if __name__ == '__main__':

    main()


from flask import Flask, request, abort

from linebot import LineBotApi, WebhookHandler
from linebot.exceptions import InvalidSignatureError
from linebot.models import *
# import button api
from linebot.models import ButtonsTemplate, MessageTemplateAction, TemplateSendMessage, PostbackTemplateAction
# import quick reply
from linebot.models import QuickReply, QuickReplyButton, LocationAction

import random
import configparser
import logging

from requests.models import Response

# import linebot回應模板
import view

# import subject/emotional辨識模型
from transformers import BertForSequenceClassification
import torch
from subject_bert import *
from emotional_bert import *

# import ckip_transformers模型
from ckip_transformers.nlp import CkipWordSegmenter, CkipPosTagger
from recognize_food_n import *

# import database similarity計算模型
from sentence_transformers import SentenceTransformer, util
from compute_n_silimar import *

app = Flask(__name__)

config = configparser.ConfigParser()
config.read('config.ini')

logging.basicConfig(level=logging.DEBUG, format="%(levelname)s %(message)s")

line_bot_api = LineBotApi(config.get('line-bot', 'channel-access-token'))
handler = WebhookHandler(config.get('line-bot', 'channel-secret'))

# subject bert model
logging.debug("載入主題模型中...")
subject_model = BertForSequenceClassification.from_pretrained("subject_model")
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
subject_model.to(device)
subject_model.eval()

# emotional bert model
logging.debug("載入情緒模型中...")
emotional_model = BertForSequenceClassification.from_pretrained(
    "emotional_model")
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
emotional_model.to(device)
emotional_model.eval()

# ckip_pos Initialize drivers
logging.debug("載入分詞模型中...")
ws_driver = CkipWordSegmenter(level=3)
pos_driver = CkipPosTagger(level=3)

# n similarity model
logging.debug("載入相似度計算模型中...")
simi_model = SentenceTransformer('distiluse-base-multilingual-cased-v2')

def cmp(w):
    """計算名詞相似度"""
    max = 0
    for i in data:
        i = i.keys()
        for word in i:
            sim = compute((word, w))
            if sim > max:
                max = sim
                ww = word
    return ww, max

def compute(wordpair):
    """計算名詞相似度"""
    embeddings = simi_model.encode(wordpair)
    distance = util.pytorch_cos_sim(embeddings[0], embeddings[1])
    return distance

@app.route("/callback", methods=['POST'])
def callback():
    # get X-Line-Signature header value
    signature = request.headers['X-Line-Signature']

    # get request body as text
    body = request.get_data(as_text=True)
    app.logger.info("Request body: " + body)

    # handle webhook body
    try:
        handler.handle(body, signature)
    except InvalidSignatureError:
        print("Invalid signature. Please check your channel access token/channel secret.")
        abort(400)

    return 'OK'

# global
ans = " "
lng = lat = 1.0
r = 0

@handler.add(MessageEvent)
# TextMessage
def handle_message(event):
    reply_all = []
    global ans, lng, lat, r

    # 處理地理座標type的訊息
    if event.message.type == 'location':
        logging.debug("接收到座標位置了")
        lat = event.message.latitude
        lng = event.message.longitude
        line_bot_api.reply_message(
            event.reply_token, view.transport())

    # 處理文字type的訊息
    elif event.message.type == 'text':
        text = event.message.text

        # 交通工具選擇
        if text == '步行' or text == '單車' or text == '機車' or text == '汽車':
            if(text == '步行'):
                r = 1000
            elif(text == '單車'):
                r = 3000
            elif(text == '機車'):
                r = 5000
            elif(text == '汽車'):
                r = 10000
            line_bot_api.reply_message(
                event.reply_token, view.open_q())

        # 聊天機器人開頭詞
        elif text == "哈囉" or text == "你好" or text == "嗨":
            line_bot_api.reply_message(
                event.reply_token, view.location())

        # 重新選擇交通工具
        elif text == "交通方式":
            line_bot_api.reply_message(
                event.reply_token, view.transport())

        # 資料庫無結果，透過GOOGLE NEARBY API進行搜尋
        elif text == '好的':
            logging.debug(f"{ans}, {lat}, {lng}, {r}")
            google_response = view.google_api(lat, lng, r, ans)

            # GOOGLE 查無結果
            if google_response == -1:
                reply_all.append(TextSendMessage(
                    text="不好意思，google map上也沒有你的搜尋結果，建議你可以嘗試輸入其他想吃的食物品項，讓我們再次為你服務"))

            # 回傳 GOOGLE 搜尋結果
            else:
                POI_name, POI_rating, POI_address, POI_open, POI_money, POI_url = google_response
                logging.debug(
                    f"{POI_name}, {POI_rating}, {POI_address},{POI_open}, {POI_money}, {POI_url}")
                reply_all.append(view.recommendation_pattern(
                    POI_name, POI_rating, POI_address, POI_open, POI_money, POI_url))

            line_bot_api.reply_message(event.reply_token, reply_all)

        # 資料庫比對無結果，且不需要透過GOOGLE幫忙搜尋
        elif text == '不需要':
            line_bot_api.reply_message(
                event.reply_token, TextSendMessage(text="請你再次輸入你想吃的食物內容"))

        # 處理開放式問答
        else:
            # 階段一：進行主題分類
            convert2tsv(text)
            testset = Review_Subject("response", tokenizer=tokenizer)
            testloader = DataLoader(testset, batch_size=1,
                                    collate_fn=create_mini_batch)

            predictions = get_predictions(subject_model, testloader)
            index_map = {v: k for k, v in testset.label_map.items()}
            predictions.tolist()
            df = pd.DataFrame({"label": predictions.tolist()})
            df['label_pre'] = df.label.apply(lambda x: index_map[x])
            df_pred = pd.concat([testset.df.loc[:, ["text"]],
                                 df.loc[:, 'label_pre']], axis=1)

            # 回傳主題分類結果
            for txt in df_pred['label_pre']:
                response = f"回答的主題是：{str(txt)}"
                subject = txt
            reply_all.append(TextSendMessage(text=response))

            if(subject == '食物'):
                # 階段二：若主題為食物，則進行情緒分類
                e_convert2tsv(text)
                testset = Review_Emotional(
                    "response_emotion", tokenizer=tokenizer)
                testloader = DataLoader(testset, batch_size=1,
                                        collate_fn=e_create_mini_batch)

                predictions = e_get_predictions(emotional_model, testloader)
                index_map = {v: k for k, v in testset.label_map.items()}
                predictions.tolist()
                e_df = pd.DataFrame({"label": predictions.tolist()})
                e_df['label_pre'] = e_df.label.apply(lambda x: index_map[x])
                e_df_pred = pd.concat([testset.df.loc[:, ["text"]],
                                       e_df.loc[:, 'label_pre']], axis=1)

                # 回傳情緒分類結果
                for txt in e_df_pred['label_pre']:
                    logging.debug(f"情緒是：{str(txt)}")
                    response = f"情緒是：{str(txt)}"
                    emotion = txt
                reply_all.append(TextSendMessage(text=response))

                # 階段三：進行詞性標記與篩選名詞
                text = [text]
                ws = ws_driver(text)
                pos = pos_driver(ws)
                for sentence_ws, sentence_pos in zip(ws, pos):
                    ans = pack_ws_pos_sentece(sentence_ws, sentence_pos)

                # 回傳名詞標記與篩選結果
                logging.debug(f"食物品項{ans}")
                reply_all.append(TextSendMessage(text=f"食物品項是：{ans}"))

                # 階段四：標記名詞與資料庫名詞進行相似度比對
                simi_food, simi_num = cmp(ans)
                logging.debug(f"資料庫比對結果為{simi_food},相似度{simi_num[0][0]:.3f}")

                # 回傳資料庫搜尋/隨機結果
                if emotion == "正面" or emotion == "中立":
                    if simi_num >= 0.8:
                        reply_all.append(TextSendMessage(
                            text=f"資料庫比對結果為:\n{simi_food}/相似度{simi_num[0][0]:.3f}"))
                        id = get_best_store(simi_food)
                        logging.debug(f"{id}")
                        result = view.get_poi_detail(id)
                        message = view.recommendation_pattern(
                            result[0], result[1], result[2], result[3], result[4], result[5])
                        reply_all.append(message)
                    else:
                        reply_all.append(TextSendMessage(
                            text=f"資料庫比對結果為:\n{simi_food}/相似度{simi_num[0][0]:.3f} \n⚠相似度過低"))
                        reply_all.append(view.google_needed())

                elif emotion == "負面":
                    reply_all.append(TextSendMessage(
                        text=f"資料庫比對結果為:\n{simi_food}/相似度{simi_num[0][0]:.3f}\n⚠我們將排除 {simi_food} 並隨機為您推薦資料庫中的店家"))
                    id = get_random_store()
                    logging.debug(f"{id}")
                    result = view.get_poi_detail(id)
                    message = view.recommendation_pattern(
                        result[0], result[1], result[2], result[3], result[4], result[5])
                    reply_all.append(message)

            # 回應主題"其他"
            elif(subject == '其他'):
                reply_all.append(TextSendMessage(
                    text="請您輸入想吃的食物品項喔！"))
            # 回應主題"價格、環境、地點、服務"
            else:
                reply_all.append(TextSendMessage(
                    text="不好意思，我們還不支援食物以外的主題喔~建議你可以重新搜尋，輸入想吃的食物品項，有助於我們更好的推薦你喔!"))

            line_bot_api.reply_message(event.reply_token, reply_all)

if __name__ == "__main__":
    # 主動推播第一則訊息
    line_bot_api.push_message(
        "Uf4811a6102c17022a991fcc3d85955b9", view.location())
    app.run(debug=True, port=8082)


#coding:utf-8
import jieba
import os
from scipy.misc import imread  # 这是一个处理图像的函数
from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator
import matplotlib.pyplot as plt

#reload(sys)

npath = os.getcwd()
filename = npath +'\\ntlk1\gg.txt'
print(filename)
gg = open(filename,'rb').read()
words = jieba.lcut( gg)
''' counts = {}
excludes = {" ", "我们","不是","两个","一个","如果","这个","那个"}
for word in words:
    if len(word) ==1:
        continue

    counts[word] = counts.get(word, 0) +1
    if word in excludes:
        del counts[word]

items = list(counts.items())
items.sort(key=lambda x:x[1], reverse=True)
for i in range(20):
    word, count = items[i]
    print("{0:<10}{1:>5}".format(word, count))
'''

imgfile = npath +'\\ntlk1\\1.jpg'
#使用词云显示
back_ground = imread(imgfile)
wc = WordCloud(background_color="white",max_words=1000, mask=back_ground, max_font_size=100,random_state=42, font_path="C:/Windows/Fonts/STFANGSO.ttf",)
wcword = ' '.join( words)
wc.generate( wcword)
# 基于彩色图像生成相应彩色
image_colors = ImageColorGenerator(back_ground)
# 显示图片
plt.imshow(wc)
# 关闭坐标轴
plt.axis('off')
# 绘制词云
plt.figure()
plt.imshow(wc.recolor(color_func=image_colors))
plt.axis('off')
# 保存图片
wc.to_file('19th.png')


import logging
import socket

from .Common.Connector import Connector

log   = logging.getLogger(__name__ + '   ')
logPT = logging.getLogger(__name__ + ':PT')
logPU = logging.getLogger(__name__ + ':PU')

class Counterpart:

    def __init__(self, port, address='0.0.0.0', probePort=0, probeAddress='0.0.0.0'):
        self.probePort    = probePort
        self.probeAddress = probeAddress
        self.con   = Connector(log,   Connector.new(socket.SOCK_DGRAM, None,      port,      address))
        self.conPU = Connector(logPU, Connector.new(socket.SOCK_DGRAM,    2, probePort, probeAddress))

    def task(self):
        data, addr = self.con.recvfrom(1024)
        try:
            token      = data[:16]
            dest       = data[16:].decode('utf-8').split('\n')
            remoteAddr = dest[0]
            remotePort = int(dest[1])
        except:
            return

        log.info('    with token: x{0}'.format(token.hex()))
        log.info('    destination: [{0}]:{1}'.format(remoteAddr, remotePort))

        if token[0] == b'T'[0]:
            with Connector(logPT, Connector.new(socket.SOCK_STREAM, 2, self.probePort, self.probeAddress)) as conPT:
                try:
                    conPT.connect((remoteAddr, remotePort))
                    conPT.sendall(data)
                except OSError as e:
                    logPT.exception(e)
                    pass
        elif token[0] == b'U'[0]:
            for _ in range(3):
                self.conPU.sendto(data, (remoteAddr, remotePort))
        else:
            log.debug('    token does not specify TCP or UDP')