import requests
import json

def post_message_to_discord(message_content):
    """
    Posts a message to a Discord channel using a webhook.

    Args:
        message_content (str): The content of the message to be posted.

    Returns:
        bool: True if the message was successfully sent, False otherwise.
    """
    webhook_url = "https://discord.com/api/webhooks/1091467606503985252/YQabxy_UNmM43faIMECzeqfLSY_F1MhGgV3Krm3aGuIypgRraGlShMgqQ9KQ6NY0933N"  # Replace with your actual webhook URL

    try:
        payload = {
            "content": message_content
        }

        headers = {
            "Content-Type": "application/json"
        }

        response = requests.post(webhook_url, data=json.dumps(payload), headers=headers)

        if response.status_code == 204:
            print("Message sent successfully!")
            return True
        else:
            print(f"Failed to send message. Status code: {response.status_code}")
            return False

    except Exception as e:
        print(f"An error occurred: {e}")
        return False


# Licensed under a 3-clause BSD style license - see LICENSE.rst

import numpy as np
import pytest

from sofia_redux.toolkit.fitting.polynomial \
    import Polyfit, linear_polyfit, gaussj_polyfit, nonlinear_polyfit

@pytest.fixture
def data():
    y, x = np.mgrid[:5, :5]
    z = 1.0 + x + (x * y) + (y ** 2)
    c = np.array([[1, 1, 0], [0, 1, 1]]).ravel()
    return x, y, z, c

def test_success(data):
    x, y, z, c = data
    poly = Polyfit(x, y, z, 2)
    assert np.allclose(poly.coefficients, c)
    assert np.allclose(poly(x, y), z)
    assert np.isclose(poly(1, 1), 4)
    r, c = poly(1, 1, dovar=True)
    assert np.allclose([r, c], [4, 0.11857142857])
    assert poly.covariance.shape == (6, 6)
    assert np.allclose(poly(x, y), z)
    assert np.isclose(poly.stats.chi2, 0)
    z[2, 2] += 1  # can't fit this exactly with 2nd order polynomial
    poly = Polyfit(x, y, z, 2)
    assert not np.isclose(poly.stats.chi2, 0)

def test_get_coefficients(data):
    x, y, z, _ = data
    poly = Polyfit(x, y, z, 2)
    c = poly.get_coefficients(covar=False)
    assert np.allclose(c, [[1, 1, 0],
                           [0, 1, 0],
                           [1, 0, 0]])
    _, c = poly.get_coefficients(covar=True)
    assert c.shape == (9, 9)
    assert np.allclose(c, c.T)
    u = np.unique(c)
    assert not np.allclose(u, u[0])

    poly = Polyfit(x, y, z, [1, 2])  # max exponent of x is 1, y is 2
    poly.get_coefficients(covar=False)

def test_robust(data):
    x, y, z, c = data
    # The fit should fail on perfect data since everything
    # will be flagged as an outlier with sufficiently low
    # rejection threshold
    poly = Polyfit(x, y, z, 2, robust=1e-6)
    assert not poly.success
    assert poly.termination == "insufficient samples remain"

    # add some noise
    rand = np.random.RandomState(42)
    noise = rand.normal(0, 1e-3, z.shape)
    z += noise

    # should only require 1 iteration
    poly = Polyfit(x, y, z, 2, robust=5)
    assert poly.termination == "delta_rms = 0"

    poly = Polyfit(x, y, z, 2, robust=-1)
    assert poly._iteration == 1

    poly = Polyfit([1, 2], [1, 2], 1, robust=-1)
    poly._iterate()
    assert poly.stats.rchi2 is np.inf
    assert np.isnan(poly.stats.q)
    assert poly.stats.dof == 0

def test_parameters_string(data):
    x, y, z, c = data
    m = Polyfit(x, y, z, 2)
    s = m._parameters_string()
    assert "(1, 1) : 1.000000 +/- 0.100000" in s
    del m.stats.sigma
    s = m._parameters_string()
    assert "+/-" not in s
    assert "(1, 1) : 1.000000" in s

def test_parse_model_args(data):
    x, y, z, c = data
    m = Polyfit(x, y, z, 2)

    with pytest.raises(ValueError) as err:
        Polyfit(x, y, z, np.ones(1))
    assert "order size does not match" in str(err.value).lower()

    with pytest.raises(ValueError) as err:
        Polyfit(x, y, z, np.ones(1), set_exponents=True)
    assert "order must have 2 features" in str(err.value).lower()

    with pytest.raises(ValueError) as err:
        Polyfit(x, y, z, np.ones((4, 3)), set_exponents=True)
    assert "dimension 1 of order does not" in str(err.value).lower()

    m = Polyfit(x, y, z, np.ones((3, 2)), set_exponents=True)
    assert m._order == -1

    with pytest.raises(ValueError) as err:
        Polyfit(x, y, z, 2, solver='foo')
    assert "unknown solver" in str(err.value).lower()

    m = Polyfit(x, y, z, 2, solver='gaussj')
    m._parse_model_args()
    assert m.fitter is gaussj_polyfit

    m = Polyfit(x, y, z, 2, solver='linear')
    m._parse_model_args()
    assert m.fitter is linear_polyfit

    m = Polyfit(x, y, z, 2, solver='nonlinear')
    m._parse_model_args()
    assert m.fitter is nonlinear_polyfit

def test_fast_error(data):
    x, y, z, c = data
    m = Polyfit(x, y, z, 2, error=np.ones_like(z))
    m._interpolated_error = None
    m._fast_error()
    assert m._interpolated_error.size == z.size
    assert np.allclose(m._interpolated_error, 1)

    m._interpolated_error = None
    m = Polyfit(x, y, z, 2, error=2.0)
    m._interpolated_error = None
    m._fast_error()
    assert m._interpolated_error.size == z.size
    assert np.allclose(m._interpolated_error, 2)

def test_refit_mask(data):
    x, y, z, c = data
    z[3:] = 1
    z[:3] = 2
    m = Polyfit(x, y, z, 1)
    m.refit_mask((z == 1).ravel(), covar=False)
    assert np.allclose(m.coefficients, [1, 0, 0])
    assert m.covariance is None
    m.refit_mask((z == 2).ravel(), covar=True)
    assert np.allclose(m.coefficients, [2, 0, 0])
    assert np.allclose(np.diag(m.covariance),
                       [3 / 10, 1 / 30, 1 / 10])

    m.refit_mask((z == 3).ravel(), covar=True)
    assert not m.success
    assert m.covariance is None

def test_refit(data):
    x, y, z, c = data
    m = Polyfit(x, y, z, 1)
    z[3:] = 1
    z[:3] = 2
    error = np.ones_like(z)
    error[z == 2] = 0
    m.refit_data(z.ravel(), error=error.ravel())
    assert np.allclose(m.coefficients, [1, 0, 0])

    m.refit_data(z.ravel(), mask=(z == 2).ravel(), error=np.ones(z.size))
    assert np.allclose(m.coefficients, [2, 0, 0])

    z.fill(3)
    m.refit_data(x, y, z, mask=np.full(z.size, True))
    assert np.allclose(m.coefficients, [3, 0, 0])


from collections import defaultdict
from typing import List

class Solution:
    def longestEqualSubarray(self, nums: List[int], k: int) -> int:
        window_start = 0
        frequency_dict = {}
        frequency_dict = defaultdict(lambda: 0, frequency_dict)
        max_arr = 0
        max_frequency = 0

        for window_end, value in enumerate(nums):
            frequency_dict[value] += 1
            max_frequency = max(max_frequency, frequency_dict[value])
            while window_end - window_start - max_frequency + 1 > k:
                frequency_dict[nums[window_start]] -= 1
                window_start += 1
            max_arr = max(max_arr, max_frequency)

        return max_arr

if __name__ == "__main__":
    s = Solution()
    print(s.longestEqualSubarray([1,3,2,3,1,3], 3))


#plot de todos os autovalores em função de v(vertices)
#um para cada rede.

import matplotlib.pyplot as plt
import numpy as np
import networkx as nx

def diretorio(matriz,caso, nome):
	matriz1 = '/home/pc/Desktop/IC/caos/arestas'
	matriz2 = '/home/pc/Desktop/IC/caos/m_complex/espectral'
	casos = ['/LM_p1','LM_int','LM_fbp','LM_c1','LM_c2','LM_fc']

	barra = '/'
	autovalor = 'autovalor'
	tipo = '.txt'

	nome = str(nome)
	caso = float(caso)
	matriz = int(matriz)

	string=''

	if (matriz == 0):

		if (caso == 3.5):
			string = str(matriz1+casos[0]+barra+nome+tipo)
		elif ((caso - 3.56995)<0.000001):
			string = str(matriz1+casos[1]+barra+nome+tipo)
		elif ((caso - 3.857)<0.0001):
			string = str(matriz1+casos[2]+barra+nome+tipo)
		elif ((caso - 3.87)<0.001):
			string = str(matriz1+casos[3]+barra+nome+tipo)
		elif ((caso - 3.89)<0.001):
			string = str(matriz1+casos[4]+barra+nome+tipo)
		elif (caso == 4):
			string = str(matriz1+casos[5]+barra+nome+tipo)
		else:
			print("Caso invalido")

	if (matriz == 1):

		if (caso == 3.5):
			string = str(matriz2+casos[0]+barra+nome+tipo)
		elif ((caso - 3.56995)<0.000001):
			string = str(matriz2+casos[1]+barra+nome+tipo)
		elif ((caso - 3.857)<0.0001):
			string = str(matriz2+casos[2]+barra+nome+tipo)
		elif ((caso - 3.87)<0.001):
			string = str(matriz2+casos[3]+barra+nome+tipo)
		elif ((caso - 3.89)<0.001):
			string = str(matriz2+casos[4]+barra+nome+tipo)
		elif (caso == 4):
			string = str(matriz2+casos[5]+barra+nome+tipo)
		else:
			print("Caso invalido")

	return string

a = float(input('Digite o caso '))
b = int(input('Digite o tamanho do arquivo txt '))

pasta = diretorio(0, a, b)

arq = open(pasta, "r")

vec=arq.readlines()

for i in range(len(vec)):
	vec[i]=vec[i].split(",")

for i in range(len(vec)):
	for j in range(2):
		vec[i][j]=float(vec[i][j])

G=nx.Graph()

G.add_edges_from(vec)

A=nx.adjacency_spectrum(G)
B=np.real(A)

arq.seek(0)
arq.close()

pasta = diretorio(1, a, b)
print(pasta)
arquivo = open(pasta,'w')

for i in range(len(vec)):
	arquivo.write(str(B[i]))
	arquivo.write("\n")

arquivo.seek(0)
arquivo.close()

ptr = open(pasta,'r')

vec=ptr.readlines()

print(vec)

for i in range(len(vec)):

	vec[i]=float(vec[i])

n = np.arange(0,len(vec),1)

plt.grid(True)
#plt.title("Autovalores em função dos vertices")
plt.xlabel("n° vertices")
lamb = "\u03BB"
plt.ylabel(lamb)
plt.plot(n,vec, color = 'k')

plt.show()

arq.close()


from django.urls import path

from . import views

app_name = 'lol'
urlpatterns = [
    path('', views.IndexView, name='index'),
    path('summoner', views.SummonerView, name='summoner'),
    path('lastgame', views.LastGameView, name='lastgame'),
    path('laststat', views.LastGameStats, name='laststat'),

]


import math
import os

import numpy as np
import pandas as pd
from ipfn import ipfn
from scipy.spatial import distance_matrix

##### Definition of input Data #####
subfolder = "FSKx"
no_of_cells = 100  # should be a number that gives a square (10x10)

## Shops Data ##
# only one chain with 5 stores distributed randomly
# The coordinates go from 0 to 1000
# The shops shouldn't be on a round number cause otherwise they're within 4 cells at the same time
# (all lists need to be the same length)
x_coord = [112, 823, 888, 105, 487]
y_coord = [198, 112, 846, 855, 537]
Chain = ["Chain 1", "Chain 1", "Chain 1", "Chain 1", "Chain 1"]
Sales = [1000, 1000, 1000, 1000, 1000]

## Population Data ##
# uniform population of 5 in each cell (500 total)
population_per_cell = 5

## Data on Shopping behavior ##
# shopping distance: 0.4 km
empirical_mean_shopping_distance = 0.4  # all units are in km
tolerance = 0.001

def check_input_data():
    # check whether all lists have the same length
    lists = [x_coord, y_coord, Chain, Sales]
    if not all(len(l) == len(lists[0]) for l in lists):
        raise ValueError(
            "Not all lists that define the shops data have the same length"
        )

    # check whether the no_of_cells gives a perfect square
    if math.isqrt(no_of_cells) ** 2 != no_of_cells:
        raise ValueError("Number of cells doesn't give a perfect square")

def import_population_data(no_of_cells, population_per_cell):
    # set values
    sqrt_cells = int(math.sqrt(no_of_cells))
    y_values = np.repeat(np.arange(50, 1000, 100), sqrt_cells)
    x_values = np.tile(np.arange(50, 1000, 100), sqrt_cells)
    df_population = pd.DataFrame(
        {
            "population": population_per_cell,
            "x_centroid": x_values,
            "y_centroid": y_values,
        }
    )
    df_population.index.names = ["Gitter_ID"]

    output_dir = os.path.join(subfolder, "Outputs", "Population")
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    df_population.to_pickle(os.path.join(output_dir, "population.pkl"))

    df_population.to_pickle(os.path.join(output_dir, "population.pkl"))
    return df_population

def import_shop_data(df_population):
    df_shops = pd.DataFrame(
        {
            "ID": range(1, len(x_coord) + 1),
            "x_coord": x_coord,
            "y_coord": y_coord,
            "Chain": Chain,
            "Sales": Sales,
            "Gitter_ID": "",
        }
    )
    for ind in df_shops.index:
        df_shops.loc[ind, "Gitter_ID"] = (
            df_population[
                ((df_population["x_centroid"] - 50) <= df_shops.x_coord[ind])
                & ((df_population["x_centroid"] + 50) >= df_shops.x_coord[ind])
                & ((df_population["y_centroid"] - 50) <= df_shops.y_coord[ind])
                & ((df_population["y_centroid"] + 50) >= df_shops.y_coord[ind])
            ].index.values
        )[0]

    output_dir = os.path.join(subfolder, "Outputs", "Stores")
    if not os.path.exists(output_dir):
        os.makedirs(output_dir)
    df_shops.to_pickle(os.path.join(output_dir, "stores.pkl"))

    return df_shops

def get_distance_matrix(production, consumption):
    production_centroids = pd.concat(
        [production.x_centroid, production.y_centroid], axis=1
    )
    consumption_centroids = pd.concat(
        [consumption.x_centroid, consumption.y_centroid], axis=1
    )

    arr_distance = distance_matrix(
        production_centroids,
        consumption_centroids,
    )
    # in-cell distance shouldn't be zero
    arr_distance[arr_distance == 0] = (128 / (45 * math.pi)) * 50

    # We need to make sure that the empirical mean shopping distance is in the same unit of measurement as the distances
    arr_distance /= 1000

    return arr_distance

def get_production_potential(shops_data):
    production_potential = shops_data.groupby("Gitter_ID").agg(
        Markets_Count=("ID", "count"),
        production_potential=("Sales", "sum"),
    )
    return production_potential

def get_consumption_potential(population_data, total_revenue):
    total_population = population_data["population"].sum()
    population_data["consumption_potential"] = (
        population_data["population"].divide(total_population)
    ).multiply(total_revenue)
    population_data = population_data[population_data["population"] != 0]
    return population_data

def furness_model(
    beta: float, dist_matrix, production_potential, consumption_potential
):
    dM = np.exp(-beta * dist_matrix)

    prod_pot_new = production_potential.production_potential.to_numpy()
    cons_pot_net = consumption_potential.consumption_potential.to_numpy()

    aggregates = [
        prod_pot_new,
        cons_pot_net,
    ]
    dimensions = [[0], [1]]
    IPF = ipfn.ipfn(dM, aggregates, dimensions)

    dM = IPF.iteration()
    flowMatrix = dM
    return flowMatrix

def get_weighted_dist(flow_matrix, dist_matrix):
    WeightDist = np.sum(flow_matrix * dist_matrix) / (np.sum(flow_matrix))
    return WeightDist

def add_indices(flow, production_potential, consumption_potential):
    df_flow = pd.DataFrame(
        flow,
        columns=consumption_potential.index,
        index=production_potential.index,
    )
    return df_flow

def hyman_model(
    empirical_mean_shopping_distance, tolerance, population_data, shops_data
):
    """calibrates the parameter (beta) of a gravity model. This parameter is the input for the furness-algorithm to calculate the flow of goods.
        Hardcoded here is the exponential distance model

    Args:
        empirical_mean_shopping_distance (float): used to compare the modeled mean distance
        tolerance (float): needed to decide when a satisfactory solution is reached

    Returns:
        flow(numpy.ndarray): _description_
    """
    beta_list = []  # keeping track of the betas
    modeled_means_list = []  # keeping track of the average of the modeled flow distance
    count_loops = 0

    # initializing Hyman with beta_0
    beta_0 = 1.0 / empirical_mean_shopping_distance
    beta_list.append(beta_0)

    production_potential = get_production_potential(shops_data)  # rows
    total_revenue = production_potential["production_potential"].sum()
    consumption_potential = get_consumption_potential(population_data, total_revenue)
    production_potential = production_potential.merge(
        population_data,
        on="Gitter_ID",
        how="left",
    )

    dist_matrix = get_distance_matrix(production_potential, consumption_potential)

    flow_0 = furness_model(
        beta_0, dist_matrix, production_potential, consumption_potential
    )

    modeled_mean_shopping_distance = get_weighted_dist(flow_0, dist_matrix)
    modeled_means_list.append(modeled_mean_shopping_distance)

    if (
        abs(empirical_mean_shopping_distance - modeled_means_list[count_loops])
        <= tolerance
    ):
        flow = flow_0
    while (
        abs(empirical_mean_shopping_distance - modeled_means_list[count_loops])
        > tolerance
    ):
        if count_loops == 0:
            beta_1 = (
                beta_0
                * modeled_means_list[count_loops]
                / empirical_mean_shopping_distance
            )
            beta_list.append(beta_1)
        elif count_loops > 0:
            beta_next = np.abs(
                (
                    (
                        (
                            empirical_mean_shopping_distance
                            - modeled_means_list[count_loops - 1]
                        )
                        * beta_list[count_loops]
                        - (
                            empirical_mean_shopping_distance
                            - modeled_means_list[count_loops]
                        )
                        * beta_list[count_loops - 1]
                    )
                    / (
                        modeled_means_list[count_loops]
                        - modeled_means_list[count_loops - 1]
                    )
                )
            )
            beta_list.append(beta_next)
        beta_current = beta_list[count_loops + 1]

        flow = furness_model(
            beta_current, dist_matrix, production_potential, consumption_potential
        )
        modeled_mean_current = get_weighted_dist(flow, dist_matrix)
        modeled_means_list.append(modeled_mean_current)

        count_loops += 1

        # break if in local minimum and check if any dist was closer to the empirical mean shopping distance
        if count_loops > 20:
            if (
                abs(
                    modeled_means_list[count_loops]
                    - modeled_means_list[count_loops - 5]
                )
            ) < 0.001:
                beta_best = beta_list[modeled_means_list.index(min(modeled_means_list))]
                flow = furness_model(
                    beta_best, dist_matrix, production_potential, consumption_potential
                )
                break

        # break if minimization routine explodes due to numerical issues
        if beta_current > 50:
            beta_best = beta_list[modeled_means_list.index(min(modeled_means_list))]
            flow = furness_model(
                beta_best, dist_matrix, production_potential, consumption_potential
            )
            break
        print(
            "On the %sd. iteration: distance between the modeled and the empirical mean shopping distance is down to %3.4f"
            % (
                count_loops,
                abs(empirical_mean_shopping_distance - modeled_means_list[count_loops]),
            )
        )

        if np.isnan(empirical_mean_shopping_distance):
            raise Exception(
                "Something went wrong, the given empirical mean shopping distance returned nan!"
            )
        if np.isnan(modeled_means_list[count_loops]):
            raise Exception(
                "Something went wrong, the current modeled mean shopping distance is nan!"
            )

    beta_best = beta_list.pop()

    # Sanity Check
    tol_this_time = np.abs(empirical_mean_shopping_distance - modeled_mean_current)
    tol_best = np.abs(
        [empirical_mean_shopping_distance - d for d in modeled_means_list]
    ).tolist()
    if tol_this_time > tol_best[tol_best.index(min(tol_best))]:
        beta_best = beta_list[tol_best.index(min(tol_best))]
        flow = furness_model(
            beta_best, dist_matrix, production_potential, consumption_potential
        )
    print(
        "On the last iteration (%2d.): tolerance is down to %3.4f"
        % (tol_best.index(min(tol_best)), tol_best[tol_best.index(min(tol_best))])
    )
    print("Beta is " + str(beta_best))

    flow_end = add_indices(flow, production_potential, consumption_potential)

    return flow_end

def main():
    check_input_data()
    df_population = import_population_data(no_of_cells, population_per_cell)
    df_shops = import_shop_data(df_population)
    flow = hyman_model(
        empirical_mean_shopping_distance, tolerance, df_population, df_shops
    )

    os.makedirs(os.path.join(subfolder, "Outputs", "Flow"), exist_ok=True)
    flow.to_pickle(os.path.join(subfolder, "Outputs", "Flow", "flow.pkl"))

if __name__ == "__main__":
    main()


from django.urls import path
from django.views.decorators.csrf import csrf_exempt

from poll.views import ActivationView, ActiveQuestionDetailView, VoteView, StatView, NomineesView, RestartPollView

urlpatterns = [
    path('<int:question_id>/activate/', csrf_exempt(ActivationView.as_view())),
    path('active/', ActiveQuestionDetailView.as_view()),
    path('<int:question_id>/vote/<int:option_id>/', csrf_exempt(VoteView.as_view())),
    path('<int:question_id>/stat/', StatView.as_view()),
    path('<int:question_id>/restart/', csrf_exempt(RestartPollView.as_view())),
    path('nominees/', NomineesView.as_view()),
]


# -*- coding: utf-8 -*-
import gzip
import urllib.request
from urllib import parse
import json
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties

class Weather:
    def __init__(self, city):
        city_name = parse.quote_plus(city)
        only_now = parse.quote_plus("")

        # download data using the API
        appid = "0b194ffd0b8273c0e43ca06ea0edf059"
        url = "https://api.shenjian.io/weather/city/?appid="+appid+"&city_name="+city_name+"&only_now="+only_now
        request = urllib.request.Request(url, headers={
        	"Accept-Encoding": "gzip",
        })
        response = urllib.request.urlopen(request)
        gzipFile = gzip.GzipFile(fileobj=response)
        text = gzipFile.read().decode('UTF-8')

        # store the temperature data
        self.data = json.loads(text)
        if self.data['error_code'] == 0:
            self.data_now = self.data['data']['now'][0]

    def day_temp(self):
        day_array = self.data['data']['forecast7'][0]['hourForcast3']
        list_time = []
        list_temp = []
        for hour in day_array:
            time = hour['time']
            temprature = hour['temprature']
            list_time.append(time)
            list_temp.append(float(temprature[:-1]))

        # set .ttc file in order to show Chinese
        font = FontProperties(fname=r"C:\\WINDOWS\\Fonts\\simsun.ttc", size=14)
        length = len(list_time)

        # draw the temperature distribution in 24 hours and save it
        plt.plot(range(length), list_temp, color='b', marker='o')
        plt.xticks(range(length), list_time, rotation=15,
                   fontproperties=font)
        for a, b in zip(range(length), list_temp):
            plt.text(a, b, b, ha='center', va='bottom', fontsize=10)
        plt.xlabel("Time", fontsize=15)
        plt.ylabel("Temperature(℃)", fontsize=15)
        plt.title("Temperature in 24 hours.", fontsize=15)
        plt.tight_layout()
        plt.savefig("day_temp.png")
        plt.close()

    def week_temp(self):
        week_array = self.data['data']['forecast7']
        list_date = []
        list_morning = []
        list_night = []
        for i in range(6):
            day = week_array[i+1]
            date = day['date']
            temp_morning = day['day'][0]['temprature']
            temp_night = day['night'][0]['temprature']
            list_date.append(date)
            list_morning.append(float(temp_morning[:-1]))
            list_night.append(float(temp_night[:-1]))

        font = FontProperties(fname=r"C:\\WINDOWS\\Fonts\\simsun.ttc", size=14)
        length = len(list_date)

        # draw the temperature distribution in 6 days and save it

        # plot the temperature in the mornings
        plt.plot(range(length), list_night, color='r', marker='o', label='night')
        for a, b in zip(range(length), list_night):
            plt.text(a, b, b, ha='center', va='bottom', fontsize=10)

        # plot the temperature in the evenings
        plt.plot(range(length), list_morning, color='b', marker='o', label='morning')
        for a, b in zip(range(length), list_morning):
            plt.text(a, b, b, ha='center', va='bottom', fontsize=10)

        # set the legend, axises and labels.
        plt.legend()
        plt.xticks(range(length), list_date, rotation=15,
                   fontproperties=font)
        plt.xlabel('Date', fontsize=15)
        plt.ylabel('Temperature(℃)', fontsize=15)
        plt.title('Temperature in 6 days', fontsize=15)
        plt.tight_layout()
        plt.savefig("week_temp.png")
        plt.close()
        return 0

if __name__ == '__main__':
    weather = Weather("合肥")
    # get the data of temprature in 7 days.
    #weather.week_temp()


import json
from datetime import datetime
from inspect import getframeinfo, stack

class i_messages:
    def __init__(self,  log_level='None', path='./log/log_config/message.json'):
        self.messages = {}
        self.path = path
        self.read_messages()
        self.log_level=log_level

    def read_messages(self):
        with open(self.path) as json_file:
            self.messages = json.load(json_file)

    def print_messages(self, m_id, ext_info=''):
        m_id = str(m_id)
        date = self.get_sysdate()
        msg=self.messages[m_id]
        caller = getframeinfo(stack()[1][0])

        if type(ext_info)==int:
            ext_info=self.messages[str(ext_info)]

        if ext_info !='':
            msg  = msg + " \n\t "+ str(ext_info)

        if m_id[0] in (["1","2","3"]):
            if str(self.log_level)=='1':
                pass
            if (str(self.log_level)=='2') or (str(self.log_level) == 'None'):
                print(date+"Info Code: "+m_id+" --> "+msg)
        elif m_id[0]=="4":
            print(date+"Warning Code: "+m_id+"\n\n"+"MessageDetails ------------>  "+ \
                  msg+ "\n\nFileName ------------>  "+caller.filename+"\n\nLineNumber ------------>  "+str(caller.lineno)+"\n\n")
        elif m_id[0]=="5":
            print(date+"Error Code: "+m_id+"\n\n"+"MessageDetails ------------>  "+ \
                  msg+ "\n\nFileName ------------>  "+caller.filename+"\n\nLineNumber ------------>  "+str(caller.lineno)+"\n\n")
            exit()

    def get_sysdate(self):
        return datetime.today().strftime('%Y-%m-%d-%H:%M:%S: ')


from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from typing import List
import datetime
import json

class LogItem(BaseModel):
    """ LogItem class to manage the log data
    """
    id: int = None # id is auto-incremented
    item_name: str
    quantity: int
    time: datetime.datetime

class Buffer:
    """ Buffer class to save the POST data
    """
    def __init__(self):
        self._buffer = None

    def update(self, new_buf):
        self._buffer = new_buf

    def save(self):
        with open("buffer.json", "w") as f:
            json.dump(self._buffer, f)

    def read(self):
        with open("buffer.json", "r") as f:
            self._buffer = json.load(f)

    @property
    def buffer(self):
        return self._buffer

#################### Main ####################s

# db = Database()
app = FastAPI()
buffer = Buffer()

#################### API ####################

@app.get("/")
async def root():
    return {"message": "Hello World"}

@app.get("/items")
async def read_item():
    return get_latest_data()

@app.post("/add_log")
async def add_log(data: str):
    try:
        response = add_log(data)
        return response
    except HTTPException as e:
        raise e
    except Exception as e:
        raise HTTPException(status_code=500, detail="Failed to process the request")

#################### Functions ####################

def get_latest_data():
    """ Get the latest log data from database

    Returns:
        list: The latest log data
    """

    return buffer.buffer

def add_log(log_data: str):
    """ Add log data to database

    Args:
        log_data (str): the original text

    Returns:
        dict: the response
    """
    data = log_data_clean(log_data)

    buffer.update(data)

    return {"message": "Successfully added the log data"}

def log_data_clean(log_data: str) -> List[LogItem]:
    """ Clean the log data

    Args:
        log_data (str): the original text

    Returns:
        str: the cleaned text

    Examples:
        >>> log_data_clean("data=Crushed Rare Earth (I) Ore~54~false;
        ····压印基板原料~0~true;
        ····drop of 熔融黑钢~0~true;")

        [LogItem(id=None, item_name='Crushed Rare Earth (I) Ore', quantity=54,
        time=datetime.datetime(2023, 7, 9, 11, 21, 25, 983932)),
        LogItem(id=None, item_name='压印基板原料', quantity=0,
        time=datetime.datetime(2023, 7, 9, 11, 21, 25, 983932)),
        LogItem(id=None, item_name='drop of 熔融黑钢', quantity=0,
        time=datetime.datetime(2023, 7, 9, 11, 21, 25, 983932))]
    """
    time = datetime.datetime.now()
    # log_data = "data=Crushed Rare Earth (I) Ore~54~false;压印基板原料~0~true;drop of 熔融黑钢~0~true;"
    log_data = log_data.split(";")
    log_data = [item.split("~") for item in log_data]
    res_data = []
    for item in log_data:
        if len(item) != 3:  # check if the data is valid
            continue
        tmp_item = LogItem(item_name=item[0], quantity=int(item[1]), time=time)
        res_data.append(tmp_item)
    return res_data


#!/usr/bin/env python3
"""Example of redis cache"""
from functools import wraps
from typing import Union, Callable, Optional
import redis
import uuid

def count_calls(method: Callable) -> Callable:
    """decorator function to define a wrapper function
    that counts times Cache class methods are called"""
    name = method.__qualname__

    @wraps(method)
    def wrapper(self, *args, **kwargs):
        """Wrapper function"""
        self._redis.incr(name)
        return method(self, *args, **kwargs)
    return wrapper

def call_history(method: Callable) -> Callable:
    """decorator func stores history of inputs and outputs for method"""
    name = method.__qualname__
    inputs = name + ':inputs'
    outputs = name + ':outputs'

    @wraps(method)
    def wrapper(self, *args, **kwargs):
        """Wrapper method"""
        self._redis.rpush(inputs, str(args))
        res = method(self, *args, **kwargs)
        self._redis.rpush(outputs, str(res))
        return res
    return wrapper

def replay(method: Callable) -> None:
    """Display history of calls of particular function"""
    name = method.__qualname__
    inputs = name + ':inputs'
    outputs = name + ':outputs'
    redis = method.__self__._redis
    count = redis.get(name).decode('utf-8')
    print('{} was called {} times:'.format(name, count))
    zipped = zip(redis.lrange(inputs, 0, -1), redis.lrange(outputs, 0, -1))
    for i, o in list(zipped):
        i = i.decode('utf-8')
        o = o.decode('utf-8')
        print('{}(*{}) -> {}'.format(name, i, o))

class Cache():
    """Class Cache generates randon key and returns it"""
    def __init__(self):
        """Cache class for caching"""
        self._redis = redis.Redis()
        self._redis.flushdb()

    @call_history
    @count_calls
    def store(self, data: Union[str, bytes, int, float]) -> str:
        """generate random key amd store input in Redis"""
        key = str(uuid.uuid4())
        self._redis.mset({key: data})
        return key

    def get(self, key: str, fn: Optional[Callable] = None) -> str:
        """Receives key and optional func that returns desired data"""
        data = self._redis.get(key)
        if fn:
            return fn(data)
        return data

    def get_str(self, data: str) -> str:
        """Get data as string"""
        return data.decode('utf-8')

    def get_int(self, data: str) -> int:
        """Get data as int"""
        return int(data)


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

import torch

def index_to_mask(index, size):
    mask = torch.zeros(size, dtype=torch.bool, device=index.device)
    mask[index] = 1
    return mask

# def random_planetoid_splits(data, num_classes, percls_trn=20, val_lb=500, Flag=1):
#     # Set new random planetoid splits:
#     # * round(train_rate*len(data)/num_classes) * num_classes labels for training
#     # * val_rate*len(data) labels for validation
#     # * rest labels for testing

#     indices = []
#     for i in range(num_classes):
#         index = (data.y == i).nonzero().view(-1)
#         index = index[torch.randperm(index.size(0))]
#         indices.append(index)

#     train_index = torch.cat([i[:percls_trn] for i in indices], dim=0)

#     if Flag is 0:
#         rest_index = torch.cat([i[percls_trn:] for i in indices], dim=0)
#         rest_index = rest_index[torch.randperm(rest_index.size(0))]

#         data.train_mask = index_to_mask(train_index, size=data.num_nodes)
#         data.val_mask = index_to_mask(rest_index[:val_lb], size=data.num_nodes)
#         data.test_mask = index_to_mask(
#             rest_index[val_lb:], size=data.num_nodes)
#     else:
#         val_index = torch.cat([i[percls_trn:percls_trn+val_lb]
#                                for i in indices], dim=0)
#         rest_index = torch.cat([i[percls_trn+val_lb:] for i in indices], dim=0)
#         rest_index = rest_index[torch.randperm(rest_index.size(0))]

#         data.train_mask = index_to_mask(train_index, size=data.num_nodes)
#         data.val_mask = index_to_mask(val_index, size=data.num_nodes)
#         data.test_mask = index_to_mask(rest_index, size=data.num_nodes)
#     return data

def random_planetoid_splits(data, num_classes, training_rate=0.1,val_lb=1):
    # Set new random planetoid splits:
    # * round(train_rate*len(data)/num_classes) * num_classes labels for training
    # * val_rate*len(data) labels for validation
    # * rest labels for testing

    indices = []
    lens=[]
    for i in range(num_classes):
        index = (data.y == i).nonzero().view(-1)
        index = index[torch.randperm(index.size(0))]
        l = round(training_rate*index.size(0))
        if l==0:
            l=1
        lens.append(l)
        indices.append(index)

    train_index = torch.cat([i[:lens[ii]] for ii, i in enumerate(indices)], dim=0)
    rest_index = torch.cat([i[lens[ii]:] for ii, i in enumerate(indices)], dim=0)

    data.train_mask = index_to_mask(train_index, size=data.num_nodes)
    data.val_mask = index_to_mask(rest_index, size=data.num_nodes)
    data.test_mask = index_to_mask(rest_index, size=data.num_nodes)

    return data

from torch_geometric.utils import homophily
import copy
import torch
import torch_geometric.utils as pyg_utils

def add_noise_to_edges(edge_index, num_nodes, noise_level):
    # 转换为有向图，这样就可以只在上三角部分添加噪声
    a,b=edge_index
    a,b=a[a<=b],b[a<=b]
    edge_index_directed=torch.vstack([a,b])

    # 获取有向图中的边的数量
    num_edges_directed = edge_index_directed.size(1)

    # 计算要添加噪声的边的数量
    num_noisy_edges = int(num_edges_directed * noise_level)

    # 从有向边中随机选择一些边来删除
    indices_to_remove = torch.randperm(num_edges_directed)[:num_noisy_edges]
    indices_to_remaining= torch.randperm(num_edges_directed)[num_noisy_edges:]

    edge_index_removed = edge_index_directed[:,indices_to_remove]
    remaining_edge_index = edge_index_directed[:,indices_to_remaining]
    #print(edge_index_removed.shape,remaining_edge_index.shape,edge_index_directed.shape)

    new_edges = []
    existing_edges = set(tuple(edge) for edge in edge_index_removed.t().tolist())
    while len(new_edges) < num_noisy_edges:
        src = torch.randint(0, num_nodes, (1,)).item()
        dst = torch.randint(0, num_nodes, (1,)).item()

        # 确保新边不在原始边集中，且源节点和目标节点不同，且满足src < dst来保证是上三角的
        if src != dst and src < dst and (src, dst) not in existing_edges:
            new_edges.append((src, dst))
            existing_edges.add((src, dst))
            existing_edges.add((dst, src))  # 由于是无向图，所以(src, dst)和(dst, src)都要加入

    # 将新边添加到边集中
    new_edge_index = torch.tensor(new_edges, dtype=torch.long).t().contiguous()
    noisy_edge_index_directed = torch.cat([remaining_edge_index, new_edge_index], dim=1)
    #print(noisy_edge_index_directed.shape)
    # 转换回无向图并返回
    noisy_edge_index = pyg_utils.to_undirected(noisy_edge_index_directed)
    #print(noisy_edge_index.shape)
    #print(edge_index.shape)

    return noisy_edge_index


#
#           _.._        ,------------.
#        ,'      `.    ( We want you! )
#       /  __) __` \    `-,----------'
#      (  (`-`(-')  ) _.-'
#      /)  \  = /  (
#     /'    |--' .  \
#    (  ,---|  `-.)__`
#     )(  `-.,--'   _`-.
#    '/,'          (  Uu",
#      (_       ,    `/,-' )
#       `.__,  : `-'/  /`--'
#        |     `--'  |
#        `   `-._   /
#         \        (
#         /\ .      \.
#        / |` \     ,-\
#       /  \| .)   /   \
#      ( ,'|\    ,'     :
#      | \,`.`--"/      }
#      `,'    \  |,'    /
#     / "-._   `-/      |
#     "-.   "-.,'|     ;
#    /        _/["---'""]
#   :        /  |"-     '
#   '           |      /
#               `      |
#
# author: OYQ
# write_date: 2023.2.28
#

import sys
import time
import pygame
from constant import *

class Game(object):
    """游戏类"""

    click1 = None
    click2 = None
    red = True
    black = False
    index = 0
    chess_left_x = []
    chess_right_x = []
    chess_up_y = []
    chess_down_y = []
    chess_left_y = None
    chess_right_y = None
    chess_up_x = None
    chess_down_x = None
    name = None
    start_click_coord = None
    old_click_coord = None
    end_click_coord = None
    go = False
    m_chess_coord = {}
    no_go_coord = {}

    def __init__(self):
        """初始化"""

        pygame.init()
        pygame.mixer.init()
        # 初始化音效
        self.move = pygame.mixer.Sound("musics/move.WAV")
        self.eat = pygame.mixer.Sound("./musics/eat.WAV")
        self.move.set_volume(1)
        self.eat.set_volume(1)
        pygame.mixer.music.load("./musics/start.mp3")
        pygame.mixer.music.set_volume(0.5)
        pygame.mixer.music.play()
        # 初始化窗口
        pygame.display.set_caption(WINDOW_TITLE)
        self.window = pygame.display.set_mode(WINDOW_SIZE)
        # 初始化图片素材
        self.ico1 = pygame.image.load("./images/ico1.png")
        self.ico2 = pygame.image.load("./images/b_j.png")
        self.r_box = pygame.image.load("images/r_box.png")
        self.b_box = pygame.image.load("images/b_box.png")
        self.dot = pygame.image.load("./images/dot.png")
        self.bg1 = pygame.image.load("images/bg1.png")
        self.bg2 = pygame.image.load("images/bg2.png")
        self.b_z = pygame.image.load("images/b_z.png")
        self.b_p = pygame.image.load("images/b_p.png")
        self.b_c = pygame.image.load("images/b_c.png")
        self.b_m = pygame.image.load("images/b_m.png")
        self.b_x = pygame.image.load("images/b_x.png")
        self.b_s = pygame.image.load("images/b_s.png")
        self.b_j = pygame.image.load("images/b_j.png")
        self.r_z = pygame.image.load("images/r_z.png")
        self.r_p = pygame.image.load("images/r_p.png")
        self.r_c = pygame.image.load("images/r_c.png")
        self.r_m = pygame.image.load("images/r_m.png")
        self.r_x = pygame.image.load("images/r_x.png")
        self.r_s = pygame.image.load("images/r_s.png")
        self.r_j = pygame.image.load("images/r_j.png")
        self.bg = self.bg1, self.bg2
        self.b_chess = self.b_z, self.b_p, self.b_c, self.b_m, self.b_x, self.b_s, self.b_j
        self.r_chess = self.r_z, self.r_p, self.r_c, self.r_m, self.r_x, self.r_s, self.r_j
        self.chess_name = {
            "黑卒": self.b_chess[0], "黑炮": self.b_chess[1],
            "黑车": self.b_chess[2], "黑马": self.b_chess[3],
            "黑象": self.b_chess[4], "黑士": self.b_chess[5],
            "黑将": self.b_chess[6], "红卒": self.r_chess[0],
            "红炮": self.r_chess[1], "红车": self.r_chess[2],
            "红马": self.r_chess[3], "红象": self.r_chess[4],
            "红士": self.r_chess[5], "红将": self.r_chess[6]}

    def img_place(self):
        """放置棋盘和棋子"""

        count_init_coord()
        self.window.blit(self.bg[1], (0, 0))
        self.window.blit(self.bg[0], (128, 0))
        self.window.blit(self.b_chess[2], INIT_COORD[0])
        self.window.blit(self.b_chess[3], INIT_COORD[1])
        self.window.blit(self.b_chess[4], INIT_COORD[2])
        self.window.blit(self.b_chess[5], INIT_COORD[3])
        self.window.blit(self.b_chess[6], INIT_COORD[4])
        self.window.blit(self.b_chess[5], INIT_COORD[5])
        self.window.blit(self.b_chess[4], INIT_COORD[6])
        self.window.blit(self.b_chess[3], INIT_COORD[7])
        self.window.blit(self.b_chess[2], INIT_COORD[8])
        self.window.blit(self.b_chess[1], INIT_COORD[9])
        self.window.blit(self.b_chess[1], INIT_COORD[10])
        self.window.blit(self.b_chess[0], INIT_COORD[11])
        self.window.blit(self.b_chess[0], INIT_COORD[12])
        self.window.blit(self.b_chess[0], INIT_COORD[13])
        self.window.blit(self.b_chess[0], INIT_COORD[14])
        self.window.blit(self.b_chess[0], INIT_COORD[15])
        self.window.blit(self.r_chess[2], INIT_COORD[16])
        self.window.blit(self.r_chess[3], INIT_COORD[17])
        self.window.blit(self.r_chess[4], INIT_COORD[18])
        self.window.blit(self.r_chess[5], INIT_COORD[19])
        self.window.blit(self.r_chess[6], INIT_COORD[20])
        self.window.blit(self.r_chess[5], INIT_COORD[21])
        self.window.blit(self.r_chess[4], INIT_COORD[22])
        self.window.blit(self.r_chess[3], INIT_COORD[23])
        self.window.blit(self.r_chess[2], INIT_COORD[24])
        self.window.blit(self.r_chess[1], INIT_COORD[25])
        self.window.blit(self.r_chess[1], INIT_COORD[26])
        self.window.blit(self.r_chess[0], INIT_COORD[27])
        self.window.blit(self.r_chess[0], INIT_COORD[28])
        self.window.blit(self.r_chess[0], INIT_COORD[29])
        self.window.blit(self.r_chess[0], INIT_COORD[30])
        self.window.blit(self.r_chess[0], INIT_COORD[31])

    def click_1(self, click1, click2):
        """第一次点击"""

        for name1, old_coord, new_coord in zip(CHESS_NAME, INIT_COORD, INIT_RANGER):
            old_x = old_coord[0]
            old_y = old_coord[1]
            new_x = new_coord[0]
            new_y = new_coord[1]
            click1_x = click1[0]
            click1_y = click1[1]
            # 判断第一次点击的坐标是不是在棋子初始坐标范围内
            if old_x <= click1_x <= new_x and old_y <= click1_y <= new_y:
                # print("{}被点击了".format(name1))
                # print("第一次点击: 棋子范围:({}~{}, {}~{}), 点击坐标:{}".format(old_x, new_x, old_y, new_y, click1))
                self.click_2(click2, name1, old_coord, new_coord)
                return

    def click_2(self, click2, name1, old_coord, new_coord):
        """第二次点击"""

        def go_on(eat):
            """继续判断"""
            for name2, init_coord, init_ranger in zip(CHESS_NAME, INIT_COORD, INIT_RANGER):
                # 判断两次点击是否都是棋子
                # if init_coord[0] < min_x < init_ranger[0] and init_coord[1] < min_y < init_ranger[1]:
                if init_coord[0] <= click2_x <= init_ranger[0] and init_coord[1] <= click2_y <= init_ranger[1]:
                    # 判断两次点击的棋子是否不一样
                    if "红" in name1 and "黑" in name2 or "黑" in name1 and "红" in name2:
                        if self.logic(init_coord):
                            eat = True
                            NAME.append(name2)
                            coord.append(init_coord)
                            un1_coord.append(init_coord)
                            un2_coord.append(init_ranger)
                            if len(NAME):
                                self.operate(len(coord), coord, old_coord, new_coord, un1_coord, un2_coord, eat, name1,
                                             name2=NAME[-1])
                                eat = False
                else:
                    for un1, un2 in zip(UNPLACED_COORD, UNPLACED_RANGER):
                        un_x1 = un1[0]
                        un_y1 = un1[1]
                        un_x2 = un2[0]
                        un_y2 = un2[1]
                        if un_x1 < min_x < un_x2 and un_y1 < min_y < un_y2:
                            coord.append(un1)
                            un1_coord.append(un1)
                            un2_coord.append(un2)
                    if len(NAME):
                        self.operate(len(coord), coord, old_coord, new_coord, un1_coord, un2_coord, eat, name1,
                                     name2=NAME[-1])
                    else:
                        self.operate(len(coord), coord, old_coord, new_coord, un1_coord, un2_coord, eat, name1,
                                     name2=None)

        for min_coord, max_coord in zip(MIN_COORD, MAX_COORD):
            min_x = min_coord[0]
            min_y = min_coord[1]
            max_x = max_coord[0]
            max_y = max_coord[1]
            click2_x = click2[0]
            click2_y = click2[1]
            # 判断第二次点击的坐标是不是在棋子可落子的坐标范围内
            if min_x <= click2_x <= max_x and min_y <= click2_y <= max_y:
                # print("第二次点击: 中心范围:({}~{}, {}~{}), 点击坐标:{}".format(min_x, max_x, min_y, max_y, click2))
                coord = []
                un1_coord = []
                un2_coord = []
                e = False
                if "红" in name1 and self.red:
                    go_on(e)
                elif "黑" in name1 and self.black:
                    go_on(e)
                else:
                    return

    def no_go(self):
        if self.red:
            pygame.display.set_icon(self.ico2)
            self.black = True
            self.red = False
        elif self.black:
            pygame.display.set_icon(self.ico1)
            self.black = False
            self.red = True

    @staticmethod
    def logic(f_coord):
        """棋子走棋逻辑判断"""
        if f_coord in FEASIBLE_COORD:
            return True
        return False

    def operate(self, flag, coord, old_coord, new_coord, un1_coord, un2_coord, eat, name1, name2):
        """棋子操作"""

        def blit(n):
            """放置棋子"""

            if eat:
                CHESS_NAME.remove(name1)
                INIT_COORD.remove(old_coord)
                INIT_RANGER.remove(new_coord)
                CHESS_NAME.remove(name2)
                INIT_COORD.remove(un1_coord[-1])
                INIT_RANGER.remove(un2_coord[-1])
                CHESS_NAME.insert(0, name1)
                INIT_COORD.insert(0, un1_coord[-1])
                INIT_RANGER.insert(0, un2_coord[-1])
                UNPLACED_COORD.insert(0, old_coord)
                UNPLACED_RANGER.insert(0, new_coord)
                # print("事件: {}吃掉了{}".format(name1, name2))
                self.eat.play()

            else:
                CHESS_NAME.remove(name1)
                INIT_COORD.remove(old_coord)
                INIT_RANGER.remove(new_coord)
                UNPLACED_COORD.remove(un1_coord[-1])
                UNPLACED_RANGER.remove(un2_coord[-1])
                CHESS_NAME.insert(0, name1)
                INIT_COORD.insert(0, un1_coord[-1])
                INIT_RANGER.insert(0, un2_coord[-1])
                UNPLACED_COORD.insert(0, old_coord)
                UNPLACED_RANGER.insert(0, new_coord)
                # print("事件: {}从{}移动到{}".format(name1, old_coord, coord[0]))
                self.move.play()

            self.window.blit(self.bg[0], (128, 0))
            for a_name, init_coord in zip(CHESS_NAME, INIT_COORD):
                CHESS_STATE[a_name] = init_coord
            if name2 is not None and eat:
                for keys, value in zip(list(CHESS_STATE.keys()), list(CHESS_STATE.values())):
                    if name2 == keys:
                        del CHESS_STATE[name2]
            if name2 is not None and not eat:
                for keys, value in zip(list(CHESS_STATE.keys()), list(CHESS_STATE.values())):
                    if name2 == keys:
                        del CHESS_STATE[name2]
            for key, value in zip(CHESS_STATE.keys(), CHESS_STATE.values()):
                if eat:
                    if name2 != key:
                        for a in self.chess_name:
                            if a in key:
                                self.window.blit(self.chess_name[a], value)
                else:
                    if name1 != key:
                        for a in self.chess_name:
                            if a in key:
                                self.window.blit(self.chess_name[a], value)

            self.go = True
            self.old_click_coord = old_coord
            self.end_click_coord = coord[0]
            self.window.blit(n, coord[0])
            self.update()
            coord.clear()

        if flag and self.logic(un1_coord[-1]):

            for name in self.chess_name.keys():
                if name in name1:
                    self.no_go()
                    blit(self.chess_name[name])
        else:
            return False

    def show_dot(self, name1, d_coord, all_coord):
        """计算棋子可以走的点位"""

        def rule():
            if (d_coord[0] == all_coord[0] or d_coord[1] == all_coord[1]) and d_coord != all_coord:
                if all_coord[0] < d_coord[0]:
                    if all_coord in INIT_COORD:
                        self.chess_left_x.append(all_coord[0])
                        self.chess_left_x.sort(reverse=True)
                        self.chess_left_y = all_coord[1]
                    else:
                        if self.chess_left_x and self.chess_left_x[0] < all_coord[0]:
                            FEASIBLE_COORD.append(all_coord)
                        elif not self.chess_left_x and all_coord[0] < d_coord[0]:
                            FEASIBLE_COORD.append(all_coord)

                elif all_coord[0] > d_coord[0]:
                    if all_coord in INIT_COORD:
                        self.chess_right_x.append(all_coord[0])
                        self.chess_right_x.sort()
                        self.chess_right_y = all_coord[1]
                    else:
                        if self.chess_right_x and all_coord[0] < self.chess_right_x[0]:
                            FEASIBLE_COORD.append(all_coord)
                        elif not self.chess_right_x and d_coord[0] < all_coord[0]:
                            FEASIBLE_COORD.append(all_coord)

                elif all_coord[1] < d_coord[1]:
                    if all_coord in INIT_COORD:
                        self.chess_up_x = all_coord[0]
                        self.chess_up_y.append(all_coord[1])
                        self.chess_up_y.sort(reverse=True)
                    else:
                        if self.chess_up_y and self.chess_up_y[0] < all_coord[1]:
                            FEASIBLE_COORD.append(all_coord)
                        elif not self.chess_up_y and all_coord[1] < d_coord[1]:
                            FEASIBLE_COORD.append(all_coord)

                elif all_coord[1] > d_coord[1]:
                    if all_coord in INIT_COORD:
                        self.chess_down_x = all_coord[0]
                        self.chess_down_y.append(all_coord[1])
                        self.chess_down_y.sort()
                    else:
                        if self.chess_down_y and all_coord[1] < self.chess_down_y[0]:
                            FEASIBLE_COORD.append(all_coord)
                        elif not self.chess_down_y and d_coord[1] < all_coord[1]:
                            FEASIBLE_COORD.append(all_coord)

        def rule2():

            if "士" in name1:
                if d_coord[0] == all_coord[0] - CHESS_INTERVAL1 and d_coord[1] == all_coord[1] - CHESS_INTERVAL1:
                    FEASIBLE_COORD.append(all_coord)
                elif d_coord[0] == all_coord[0] + CHESS_INTERVAL1 and d_coord[1] == all_coord[1] - CHESS_INTERVAL1:
                    FEASIBLE_COORD.append(all_coord)
                elif d_coord[0] == all_coord[0] - CHESS_INTERVAL1 and d_coord[1] == all_coord[1] + CHESS_INTERVAL1:
                    FEASIBLE_COORD.append(all_coord)
                elif d_coord[0] == all_coord[0] + CHESS_INTERVAL1 and d_coord[1] == all_coord[1] + CHESS_INTERVAL1:
                    FEASIBLE_COORD.append(all_coord)
            elif "将" in name1:
                if d_coord[0] == all_coord[0] - CHESS_INTERVAL1 and d_coord[1] == all_coord[1]:
                    FEASIBLE_COORD.append(all_coord)
                elif d_coord[0] == all_coord[0] + CHESS_INTERVAL1 and d_coord[1] == all_coord[1]:
                    FEASIBLE_COORD.append(all_coord)
                elif d_coord[0] == all_coord[0] and d_coord[1] == all_coord[1] - CHESS_INTERVAL1:
                    FEASIBLE_COORD.append(all_coord)
                elif d_coord[0] == all_coord[0] and d_coord[1] == all_coord[1] + CHESS_INTERVAL1:
                    FEASIBLE_COORD.append(all_coord)

        if "红卒" in name1 and all_coord[1] <= d_coord[1]:
            if d_coord[1] <= 226:
                if d_coord[0] - CHESS_INTERVAL1 == all_coord[0] and d_coord[1] == all_coord[1]:
                    FEASIBLE_COORD.append(all_coord)
                elif d_coord[0] + CHESS_INTERVAL1 == all_coord[0] and d_coord[1] == all_coord[1]:
                    FEASIBLE_COORD.append(all_coord)
                elif d_coord[0] == all_coord[0] and d_coord[1] - CHESS_INTERVAL1 == all_coord[1]:
                    FEASIBLE_COORD.append(all_coord)
            elif all_coord[0] == d_coord[0] and d_coord[1] - CHESS_INTERVAL1 == all_coord[1]:
                FEASIBLE_COORD.append(all_coord)

        elif "黑卒" in name1 and all_coord[1] >= d_coord[1]:
            if d_coord[1] >= 282:
                if d_coord[0] - CHESS_INTERVAL1 == all_coord[0] and d_coord[1] == all_coord[1]:
                    FEASIBLE_COORD.append(all_coord)
                elif d_coord[0] + CHESS_INTERVAL1 == all_coord[0] and d_coord[1] == all_coord[1]:
                    FEASIBLE_COORD.append(all_coord)
                elif d_coord[0] == all_coord[0] and d_coord[1] + CHESS_INTERVAL1 == all_coord[1]:
                    FEASIBLE_COORD.append(all_coord)
            elif all_coord[0] == d_coord[0] and d_coord[1] + CHESS_INTERVAL1 == all_coord[1]:
                FEASIBLE_COORD.append(all_coord)

        elif "炮" in name1 or "车" in name1:
            rule()
        elif "马" in name1:
            self.m_chess_coord["up_left"] = d_coord[0] - CHESS_INTERVAL1, d_coord[1] - CHESS_INTERVAL1 * 2
            self.m_chess_coord["up_right"] = d_coord[0] + CHESS_INTERVAL1, d_coord[1] - CHESS_INTERVAL1 * 2
            self.m_chess_coord["left_up"] = d_coord[0] - CHESS_INTERVAL1 * 2, d_coord[1] - CHESS_INTERVAL1
            self.m_chess_coord["left_down"] = d_coord[0] - CHESS_INTERVAL1 * 2, d_coord[1] + CHESS_INTERVAL1
            self.m_chess_coord["right_up"] = d_coord[0] + CHESS_INTERVAL1 * 2, d_coord[1] - CHESS_INTERVAL1
            self.m_chess_coord["right_down"] = d_coord[0] + CHESS_INTERVAL1 * 2, d_coord[1] + CHESS_INTERVAL1
            self.m_chess_coord["down_left"] = d_coord[0] - CHESS_INTERVAL1, d_coord[1] + CHESS_INTERVAL1 * 2
            self.m_chess_coord["down_right"] = d_coord[0] + CHESS_INTERVAL1, d_coord[1] + CHESS_INTERVAL1 * 2
            self.no_go_coord["go_left"] = d_coord[0] - CHESS_INTERVAL1, d_coord[1]
            self.no_go_coord["go_right"] = d_coord[0] + CHESS_INTERVAL1, d_coord[1]
            self.no_go_coord["go_up"] = d_coord[0], d_coord[1] - CHESS_INTERVAL1
            self.no_go_coord["go_down"] = d_coord[0], d_coord[1] + CHESS_INTERVAL1
        elif "象" in name1:
            self.m_chess_coord["up_left"] = d_coord[0] - CHESS_INTERVAL1 * 2, d_coord[1] + CHESS_INTERVAL1 * 2
            self.m_chess_coord["up_right"] = d_coord[0] + CHESS_INTERVAL1 * 2, d_coord[1] + CHESS_INTERVAL1 * 2
            self.m_chess_coord["down_left"] = d_coord[0] - CHESS_INTERVAL1 * 2, d_coord[1] - CHESS_INTERVAL1 * 2
            self.m_chess_coord["down_right"] = d_coord[0] + CHESS_INTERVAL1 * 2, d_coord[1] - CHESS_INTERVAL1 * 2
            self.no_go_coord["up_left"] = d_coord[0] - CHESS_INTERVAL1, d_coord[1] + CHESS_INTERVAL1
            self.no_go_coord["up_right"] = d_coord[0] + CHESS_INTERVAL1, d_coord[1] + CHESS_INTERVAL1
            self.no_go_coord["down_left"] = d_coord[0] - CHESS_INTERVAL1, d_coord[1] - CHESS_INTERVAL1
            self.no_go_coord["down_right"] = d_coord[0] + CHESS_INTERVAL1, d_coord[1] - CHESS_INTERVAL1

        elif "士" in name1 or "将" in name1:
            if "红" in name1:
                if CHESS_INTERVAL1 * 3 + CHESS_X <= all_coord[0] <= CHESS_INTERVAL1 * 5 + CHESS_X and CHESS_INTERVAL1 * 7 + CHESS_Y <= all_coord[1] <= CHESS_INTERVAL1 * 9 + CHESS_Y:
                    rule2()
            elif "黑" in name1:
                if CHESS_INTERVAL1 * 3 + CHESS_X <= all_coord[0] <= CHESS_INTERVAL1 * 5 + CHESS_X and CHESS_Y <= all_coord[1] <= CHESS_INTERVAL1 * 2 + CHESS_Y:
                    rule2()

    @staticmethod
    def play_music(music):
        """播放音频"""
        pygame.mixer.music.load("./musics/{}".format(music))
        pygame.mixer.music.set_volume(0.5)
        pygame.mixer.music.play()

    def event(self):
        """事件判断"""

        name = None
        all_music, num_list, index = random_num()
        print(all_music, num_list, index)
        while True:
            time.sleep(0.001)

            if not pygame.mixer.music.get_busy():
                music = all_music[num_list[self.index]]
                print(music, self.index)
                if self.index < index:
                    self.play_music(music)
                    self.index += 1
                    if self.index == index:
                        self.index = 0

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()

                elif event.type == pygame.MOUSEBUTTONDOWN:
                    if event.button == 1:
                        if self.click1 is None:
                            self.click1 = event.pos
                            if len(FEASIBLE_COORD):
                                FEASIBLE_COORD.clear()
                                self.chess_left_x.clear()
                                self.chess_right_x.clear()
                                self.chess_up_y.clear()
                                self.chess_down_y.clear()
                                self.m_chess_coord.clear()
                                self.no_go_coord.clear()
                            for n, old_coord, new_coord in zip(CHESS_NAME, INIT_COORD, INIT_RANGER):
                                old_x = old_coord[0]
                                old_y = old_coord[1]
                                new_x = new_coord[0]
                                new_y = new_coord[1]
                                click1_x = event.pos[0]
                                click1_y = event.pos[1]
                                CHESS_INIT[n] = old_coord
                                if old_x <= click1_x <= new_x and old_y <= click1_y <= new_y:
                                    name = n
                                    self.name = n
                                    self.start_click_coord = old_coord
                                    self.window.blit(self.r_box, old_coord)
                                    self.update()
                            all_coord = INIT_COORD + UNPLACED_COORD
                            if self.start_click_coord is not None:
                                for coord in all_coord:
                                    self.show_dot(name, self.start_click_coord, coord)
                                if "炮" in self.name:
                                    if len(self.chess_left_x) >= 2:
                                        FEASIBLE_COORD.append((self.chess_left_x[1], self.chess_left_y))
                                    if len(self.chess_right_x) >= 2:
                                        FEASIBLE_COORD.append((self.chess_right_x[1], self.chess_right_y))
                                    if len(self.chess_up_y) >= 2:
                                        FEASIBLE_COORD.append((self.chess_up_x, self.chess_up_y[1]))
                                    if len(self.chess_down_y) >= 2:
                                        FEASIBLE_COORD.append((self.chess_down_x, self.chess_down_y[1]))
                                elif "车" in self.name:
                                    print(self.chess_left_x)
                                    if len(self.chess_left_x) >= 1:
                                        FEASIBLE_COORD.append((self.chess_left_x[0], self.chess_left_y))
                                    if len(self.chess_right_x) >= 1:
                                        FEASIBLE_COORD.append((self.chess_right_x[0], self.chess_right_y))
                                    if len(self.chess_up_y) >= 1:
                                        FEASIBLE_COORD.append((self.chess_up_x, self.chess_up_y[0]))
                                    if len(self.chess_down_y) >= 1:
                                        FEASIBLE_COORD.append((self.chess_down_x, self.chess_down_y[0]))
                                elif "马" in self.name:
                                    for key1, value1 in self.no_go_coord.items():
                                        for key2, value2 in self.m_chess_coord.items():
                                            if value1 not in INIT_COORD and value1 in UNPLACED_COORD:
                                                if key1[3:] == key2[:2] or key1[3:] == key2[:4] or key1[3:] == key2[:5]:
                                                    if CHESS_X <= value2[0] <= CHESS_INTERVAL1 * 8 + CHESS_X and CHESS_Y <= value2[1] <= CHESS_INTERVAL1 * 9 + CHESS_Y:
                                                        FEASIBLE_COORD.append(value2)
                                elif "象" in self.name:
                                    for key3, value3 in self.no_go_coord.items():
                                        for key4, value4 in self.m_chess_coord.items():
                                            if value3 not in INIT_COORD and value3 in UNPLACED_COORD:
                                                if key3 == key4:
                                                    if CHESS_X <= value4[0] <= CHESS_INTERVAL1 * 8 + CHESS_X and CHESS_Y <= value4[1] <= CHESS_INTERVAL1 * 9 + CHESS_Y:
                                                        if "红" in self.name and value4[1] >= 282:
                                                            FEASIBLE_COORD.append(value4)
                                                        elif "黑" in self.name and value4[1] <= 226:
                                                            FEASIBLE_COORD.append(value4)
                                if not self.go:
                                    for key, value in CHESS_INIT.items():
                                        if value in FEASIBLE_COORD:
                                            if self.name[0] == key[0]:
                                                FEASIBLE_COORD.remove(value)
                                elif self.go:
                                    for key, value in CHESS_STATE.items():
                                        if value in FEASIBLE_COORD:
                                            if self.name[0] == key[0]:
                                                FEASIBLE_COORD.remove(value)

                                for a_coord in FEASIBLE_COORD:
                                    self.window.blit(self.dot, a_coord)
                                self.update()

                        else:
                            self.click2 = event.pos
                            self.click_1(self.click1, self.click2)
                            print("当前 red:{},black:{}".format(self.red, self.black))
                            self.click1 = None
                            self.click2 = None
                            if not self.go:
                                self.window.blit(self.bg[0], (128, 0))
                                for chess_name in self.chess_name.keys():
                                    for key, value in CHESS_INIT.items():
                                        if chess_name in key:
                                            self.window.blit(self.chess_name[chess_name], value)
                            else:
                                self.window.blit(self.bg[0], (128, 0))
                                for chess_name in self.chess_name.keys():
                                    for key, value in CHESS_STATE.items():
                                        if chess_name in key:
                                            self.window.blit(self.chess_name[chess_name], value)
                                self.window.blit(self.b_box, self.old_click_coord)
                                self.window.blit(self.b_box, self.end_click_coord)
                            self.update()

    @staticmethod
    def update():
        pygame.display.update()

if __name__ == "__main__":
    game = Game()
    game.img_place()
    game.update()
    game.event()


import pandas as pd
from tqdm import tqdm
from multiprocessing.pool import Pool
import numpy as np
import os
import subprocess
import shutil
import zipfile

def convert_mp4_to_zip_ffmpeg(mp4_path: str,
                              zip_path: str,
                              fps: int = None,
                              uniform_num_frames: int = None,
                              scale: int = None,
                              start_time: int = 0,
                              quality: int = 2,
                              duration: int = None,
                              override: bool = True):
    if os.path.isfile(zip_path):
        if override:
            os.remove(zip_path)
        else:
            return 0

    output_dir = os.path.dirname(zip_path)
    tmp_dir = os.path.join(output_dir, '{}_tmp'.format(os.path.basename(zip_path)[:-4]))
    if not os.path.isdir(tmp_dir):
        os.makedirs(tmp_dir, exist_ok=True)

    cmd = f"ffmpeg -nostdin -y -i {mp4_path} -start_number 0 -q 0 -vf fps=1 {tmp_dir}/%07d.jpg"
    try:
        with open(os.devnull, "w") as null:
            subprocess.call(cmd, shell=True, timeout=60, stderr=null)
    except subprocess.TimeoutExpired:
        shutil.rmtree(tmp_dir)
        return -1
    else:
        imgpaths = [os.path.join(tmp_dir, fn) for fn in os.listdir(tmp_dir) if fn.endswith('.jpg')]
        #inds = np.linspace(0, len(imgpaths) - 1, uniform_num_frames, dtype=int).tolist()
        #imgpaths = [imgpaths[i] for i in inds]
        if len(imgpaths) != 0:
            with zipfile.ZipFile(zip_path, 'w') as wzip:
                for p in imgpaths:
                    name = p.split("/")[-1]
                    wzip.write(p, arcname=name)
        shutil.rmtree(tmp_dir)

    return 0

def do_convert(args):
    # mode, token, idx, fps = args
    mode, token, idx, fps = args
    video_path = "../data/videos/%s/%s/%s.mp4" % (mode, token, idx)
    zip_path = "../data/jpg_zips/%s/%s.zip" % (idx[-2:], idx)
    convert_mp4_to_zip_ffmpeg(video_path, zip_path, fps=fps)

def main():
    train_query_meta = "../data/meta/train/train_query_metadata.csv"
    train_ref_meta = "../data/meta/train/train_reference_metadata.csv"
    test_query_meta = "../data/meta/test/test_query_metadata.csv"
    test_ref_meta = "../data/meta/test/test_reference_metadata.csv"

    meta_query = pd.read_csv(train_query_meta)
    meta_ref = pd.read_csv(train_ref_meta)
    meta_query_ = pd.read_csv(test_query_meta)
    meta_ref_ = pd.read_csv(test_ref_meta)

    meta = pd.concat([meta_query, meta_ref], ignore_index=True)
    meta["mode"] = "train"

    meta_ = pd.concat([meta_query_, meta_ref_], ignore_index=True)
    meta_["mode"] = "test"
    meta = pd.concat([meta, meta_], ignore_index=True)

    video_list = meta["video_id"].tolist()
    modes = meta["mode"].tolist()

    args_list = []
    for idx, m in zip(video_list, modes):
        t = "query" if idx.startswith("Q") else "reference"

        args_list.append((m, t, idx, 1))

    print("#####", len(video_list))

    with Pool(16) as pool:
        pool.map(do_convert, tqdm(args_list))
    pool.join()

if __name__ == "__main__":
    main()


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

# @File  : nova_aggregate_host_relation_table.py
# @Author: gaofzhan
# @Email: gaofeng.a.zhang@ericssoin.com
# @Date  : 2020/12/3 13:45
# @Desc  : nova aggregate-show <ha-id>

from backend.myBluePrint.ericic_v2.model.ericic_base_model import BASE
from sqlalchemy import Column, String, Integer, TEXT, PrimaryKeyConstraint

class AggregateHostRelation(BASE):
    __tablename__ = 'nova_aggregate_host_relation_table'

    ag_id = Column(String(255), nullable=False)
    aggregate_name = Column(String(255), )
    availability_zone = Column(String(255), )
    host = Column(String(255), )
    meta_data = Column(String(255), )
    dc_id = Column(String(50), nullable=False)
    timestamp = Column(Integer(), nullable=False)

    __table_args__ = (
        PrimaryKeyConstraint('host', 'dc_id', 'ag_id'),
    )

    def __init__(self, ag_id, aggregate_name, availability_zone, host, meta_data, dc_id, timestamp):
        self.ag_id = ag_id
        self.aggregate_name = aggregate_name
        self.availability_zone = availability_zone
        self.host = host
        self.meta_data = meta_data
        self.dc_id = dc_id
        self.timestamp = timestamp


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue May  5 11:50:19 2020

@author: nsai
"""
import xlrd
import re
import nltk
from nltk.corpus import stopwords
from sklearn.feature_extraction.text import TfidfVectorizer
from unicodedata import normalize
from sklearn.neighbors import NearestNeighbors
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.cluster import MiniBatchKMeans
import numpy as np
import pandas as pd
## The general approach is to creat TF-IDF vectors and then using K-means for clustering

## Opening xlsx file

wb = xlrd.open_workbook("/Users/nsai/Downloads/OneDrive_1_30-04-2020/Company Descriptions.xlsx")

longCompanyDescp = []
companyName = []

## Creating a List of company names and company description from the file

for s in wb.sheets():
    for row in range(1,s.nrows,1):
            companyName.append(s.cell(row,0).value)
            if s.cell(row,2).value == "":
                longCompanyDescp.append(s.cell(row,1).value)
            else :
                longCompanyDescp.append(s.cell(row,2).value)

## Creating a dictionary of Company names and their description as k,v pairs

company_dict = dict(zip(companyName,longCompanyDescp))

##Cleaning description by removing stop words and numbers

def clean_descp(text):
    letters_only = re.sub('[^a-zA-Z]', ' ', text)
    words = letters_only.lower().split()
    new_words = []
    for w in words:
        w_norm = normalize('NFKD', w).encode('ASCII','ignore').decode('ASCII')
        new_words.append(w_norm)
    stopwords_eng = set(stopwords.words("english"))
    useful_words = [x for x in new_words if not x in stopwords_eng]

    # Combine words into a paragraph again

    useful_words_string = ' '.join(useful_words)
    return(useful_words_string)

clean_companyDescp = map(clean_descp,longCompanyDescp)
clean_company_dict = dict(zip(companyName,clean_companyDescp))

## Creating TF-IDF Vectors from the descriptions

def tokenize(text):
    tokens = nltk.word_tokenize(text)
    #stems = stem_words(tokens, stemmer)
    return tokens

tfidf = TfidfVectorizer(tokenizer=tokenize, stop_words='english')
tfs = tfidf.fit_transform(clean_company_dict.values())

#Finding Nearest Neighbours

model_tf_idf = NearestNeighbors(metric='cosine', algorithm='brute')
model_tf_idf.fit(tfs)

#Inputs a query tf_idf vector, the dictionary of companies, the knn model, and the number of neighbors
#Prints the k nearest neighbors

def print_nearest_neighbors(query_tf_idf, full_company_dictionary, knn_model, k):
    distances, indices = knn_model.kneighbors(query_tf_idf, n_neighbors = k+1)
    nearest_neighbors = [list(full_company_dictionary.keys())[x] for x in indices.flatten()]

    for company in range(len(nearest_neighbors)):
        if company == 0:
            print ('Query Company: {0}\n'.format(nearest_neighbors[company]))
        else:
            print ('{0}: {1}\n'.format(company, nearest_neighbors[company]))

print_nearest_neighbors(tfs[8], clean_company_dict, model_tf_idf, k=5)

## Calculating the right number of clusters by plotting
## the Sum of Squared Errors for different clusters and finding the elbow

def find_optimal_clusters(data, max_k):
    iters = range(2, max_k+1, 4)
    sse = []
    for k in iters:
        sse.append(MiniBatchKMeans(n_clusters=k).fit(data).inertia_)
        print('Fit {} clusters'.format(k))

    f, ax = plt.subplots(1, 1)
    ax.plot(iters, sse, marker='o')
    ax.set_xlabel('Cluster Centers')
    ax.set_xticks(iters)
    ax.set_xticklabels(iters)
    ax.set_ylabel('SSE')
    ax.set_title('SSE by Cluster Center Plot')

find_optimal_clusters(tfs,40)

##Running k-means and plotting with k obtained from elbow method

k = 28
km = KMeans(n_clusters=k, init='k-means++', max_iter=100, n_init=5,
                verbose=1)
km.fit(tfs)

## Assigning cluster values to companies as a dictionary

cluster_assignment_dict = {}

for i in set(km.labels_):
    current_cluster_companies = [list(clean_company_dict.keys())[x] for x in np.where(km.labels_ == i)[0]]
    cluster_assignment_dict[i] = current_cluster_companies

## Assigning  Labels to clusters using description of companies in that cluster
cluster_themes_dict = {}

for key in cluster_assignment_dict.keys():
    current_tfidf = TfidfVectorizer(tokenizer=tokenize, stop_words='english')
    current_tfs = current_tfidf.fit_transform(map(clean_descp,cluster_assignment_dict[key]))
    current_tf_idfs = dict(zip(current_tfidf.get_feature_names(), current_tfidf.idf_))
    tf_idfs_tuples = current_tf_idfs.items()
    cluster_themes_dict[key] = sorted(tf_idfs_tuples, key = lambda x: x[1])[:1]

##Output format

compList = []
labelList = []
for v in cluster_assignment_dict.values():
    compList.append(v)

for values in cluster_themes_dict.values():
    labelList.append(values[0][0])

def createDict(label,comp):
    labelCol = []
    for i in range(len(comp)):
        labelCol.append(label)
    df  = pd.DataFrame(list(zip(labelCol,comp)),columns = ["Label","Company"])
    df.to_csv("/Users/nsai/Documents/Research/task3_2.csv",mode = "a")

for i in range(0,27,1):
    createDict(labelList[i],compList[i])


import os
import json
import glob
import numpy as np
import seaborn as sns

import torch
import torch.nn as nn
import torch.optim as optim
from tqdm import tqdm

from idgl_utils.generic_utils import to_cuda
from idgl_utils.constants import VERY_SMALL_NUMBER
import torch.nn.functional as F
import shutil

import os
import sys
proj_dir = os.path.dirname(os.path.abspath(__file__))
sys.path.append(proj_dir) # 将路径添加到环境目录
from idgl_utils.idgl_utils import AverageMeter
from model.model_idgl import IDGL

class ModelHandler(object):
    def __init__(self, config, train_loader, val_loader, test_loader, adj0, dist, angle_adj):
        self.config = config
        """
            1 创建评价指标 并指定数据结构
        """
        # 训练集损失 验证集损失 测试集损失 均方根误差列表
        self.train_loss_list, self.val_loss_list, self.test_loss_list, self.rmse_list = [], [], [], []

        """
            2 确定运行设备
        """
        use_cuda = torch.cuda.is_available()
        # if use_cuda:
        #     print('[Using CUDA]')
        # else:
        #     print("[Using CPU]")
        self.device = torch.device('cuda' if use_cuda else 'cpu')
        self.config['device'] = self.device

        """
            3 设置随机种子应用到设备
        """
        seed = self.config['idgl'].get('seed',42)
        np.random.seed(seed)
        torch.manual_seed(seed)
        if self.device:
            torch.cuda.manual_seed(seed)

        """
            4 准备数据集
        """
        self.train_loader = train_loader
        self.val_loader = val_loader
        self.test_loader = test_loader
        self.adj0 = adj0
        np.save("result/adj0.npy",self.adj0.cpu().detach().numpy())
        """
            5 model初始化并打印模型信息和参数总数
        """
        self.model = IDGL(config)
        self.model = self.model.to(self.device)
        self.config = self.model.config
        self.is_test = False
        self.firstModelLoad = True
        # print(self.model)

        # num_params = 0
        # for name,p in self.model.named_parameters():
        #     print('{}: {}'.format(name, str(p.size())))
        #     num_params += p.numel()
        # print('#Parameters = {}\n'.format(num_params))

        """
            6 确定使用哪种优化器 定义计算RMSE函数
        """
        self.init_optimizer()
        self.criterion = nn.MSELoss()

        """
            7 读入 dist 和 angle
        """
        self.dist = dist
        self.angle_adj = angle_adj

    # 初始化优化器
    def init_optimizer(self):
        parameters = [p for p in self.model.parameters() if p.requires_grad]
        if self.config['train']['optimizer'] == 'sgd':
            self.optimizer = optim.SGD(parameters, self.config['train']['lr'],
                                       momentum=self.config['momentum'],
                                       weight_decay=self.config['train']['weight_decay'])
        elif self.config['train']['optimizer'] == 'adam':
            self.optimizer = optim.Adam(parameters, lr=self.config['train']['lr'],
                                        weight_decay=self.config['train']['weight_decay'])
        elif self.config['train']['optimizer'] == 'adamax':
            self.optimizer = optim.Adamax(parameters, lr=self.config['train']['lr'])
        elif self.config['train']['optimizer'] == 'rmsprop':
            self.optimizer = optim.RMSprop(parameters,lr=self.config['train']['lr'],
                                           weight_decay=self.config['train']['weight_decay'])
        else:
            raise RuntimeError('Unsupported optimizer: %s' % self.config['train']['optimizer'])
        # self.scheduler = ReduceLROnPlateau(self.optimizer, mode='max', factor=self.config['train']['lr_reduce_factor'], \
        #                                    patience=self.config['train']['lr_patience'], verbose=True) # 动态调整学习率

    # 训练过程
    def train(self,epoch):
        if self.train_loader is None:
            print("No training set specified -- skipped training")
            return
        self.epoch_num = epoch
        train_loss = self.run_whole_epoch(self.train_loader,task_type="train",verbose=self.config['idgl']['verbose'])
        # self.train_loss_list.append(train_loss.item())
        torch.cuda.empty_cache()

        return train_loss

    # 验证过程
    def val(self):
        if self.val_loader is None:
            print("No val set specified -- skipped training")
            return

        val_loss = self.run_whole_epoch(self.val_loader,task_type="val",verbose=self.config['idgl']['verbose'])
        torch.cuda.empty_cache()

        return val_loss

    # 测试过程
    def test(self,t2m_mean,t2m_std):

        self.t2m_mean = t2m_mean
        self.t2m_std = t2m_std
        test_loss = self.run_whole_epoch(self.test_loader,task_type="test",verbose=self.config['idgl']['verbose'])
        torch.cuda.empty_cache()

        return test_loss, self.predict_epoch,self.label_epoch,self.time_epoch

    # graph learn + train phase
    def run_whole_epoch(self,data_loader,task_type,verbose=None,out_predictions=False):

        if task_type == "train":
            self.model.train()
            if os.path.exists("./save_train_param/Param0.pth") :
                load_data = torch.load("./save_train_param/Param0.pth")
                self.model.load_state_dict(load_data)
        else:
            self.model.eval()

        if task_type == "test":
            self.predict_list = []
            self.label_list = []
            self.time_list = []

        loss = 0
        total_loss = torch.tensor(0.,requires_grad=False)
        hist_len = self.config['train']['hist_len']
        pth_idx = 0
        save_range = self.config['train']['batch_epoch']
        load_modelParam = False
        is_mean_curA = True
        pth_idx_str = "./save_train_param/Param"

        # 每个batch分别做训练
        for batch_idx,data in enumerate(tqdm(data_loader)):
            self.optimizer.zero_grad()  # 梯度置0
            feature,t2m,timestamp_arr = data
            feature = feature.to(self.device) # (7,6,2160,3)
            acc_u = feature[:, :, :, -5:-4]
            acc_v = feature[:, :, :, -4:-3]
            uv_angleACC = feature[:, :, :, -3:-2]
            uv_angle = feature[:, :, :, -2:-1]
            speed = feature[:, :, :, -1:]
            feature = feature[:, :, :, 0:-5]
            t2m = t2m.to(self.device)
            t2m_label = t2m[:,hist_len:] # (batch_size,pred_len=5,station_num,attr_num)
            t2m_hist = t2m[:,:hist_len] # (batch_size,hist_len=1,station_num,attr_num)
            t2m_trueData = t2m_hist[:,-1]

            feature_trueData = feature[:,:hist_len]
            acc_u = acc_u[:,:hist_len]
            acc_v = acc_v[:,:hist_len]
            uv_angleACC = uv_angleACC[:,:hist_len]
            uv_angle = uv_angle[:,:hist_len]
            speed = speed[:,:hist_len]

            feature_trueData = feature_trueData[:,-1]
            acc_u = acc_u[:,-1]
            acc_v = acc_v[:,-1]
            uv_angleACC = uv_angleACC[:,-1]
            uv_angle = uv_angle[:,-1]
            speed = speed[:,-1]

            slideWindow_first_day_feature = torch.cat((t2m_trueData,feature_trueData),dim=-1)
            max_iter = self.config['idgl'].get('max_iter', 10)
            self.adj0 = self.adj0.to(self.device)

            # 重新初始化模型并进行读取数值
            if load_modelParam:
                modelA = IDGL(self.config)
                self.model = modelA.to(self.device)
                load_data = torch.load(pth_idx_str) if task_type == "train" else torch.load("./save_train_param/Param0.pth")
                self.model.load_state_dict(load_data)
                pth_idx_str = "./save_train_param/Param"
                loss = torch.tensor(0)
                load_modelParam = False
                if self.config['idgl']['graph_learn']:
                    node_vec = self.node_vec1

            """ 是否进行图学习 """
            if self.config['idgl']['graph_learn'] :
                # 第一轮使用初始特征 后期使用GCN的Embedding
                node_vec = slideWindow_first_day_feature if batch_idx == 0 else node_vec

                # 判断本轮是否进行图学习
                if batch_idx % (2*save_range) == 0 : # batch_idx < max_iter and self.diff(cur_raw_adj,pre_raw_adj,first_raw_adj).item() > eps_adj
                    # load_cur_adj1 = False

                    cur_raw_adj, cur_adj = self.model.learn_graph(graph_learner=self.model.graph_learner,
                                                                  gl_feature=node_vec,
                                                                  graph_skip_conn=self.config['idgl']['graph_skip_conn'],
                                                                  graph_include_self=self.model.graph_include_self,
                                                                  init_adj=self.adj0,
                                                                  dist= self.dist,
                                                                  angle=self.angle_adj,
                                                                  uv_angle=uv_angle,
                                                                  uv_angleACC=uv_angleACC,
                                                                  acc_u=acc_u,
                                                                  acc_v=acc_v,
                                                                  speed=speed)  # GL(Z(t-1))
                    graphLoss_update_continue = True
                    is_mean_curA = True

                    # epoch = 1 and batch_idx = 0 : save adj's npy
                    if self.epoch_num == 1 and batch_idx < 6:
                        cur_ad = 255 * cur_adj
                        save_adj_new = "result/epoch=" + str(self.epoch_num) + "_adj1.npy"
                        np.save(save_adj_new, cur_ad.cpu().detach().numpy())

                else: # 不进行图学习时
                    is_mean_curA = False
                    graphLoss_update_continue = False # 是否还继续更新graphLoss
                    cur_adj = self.cur_adj1

            else: #  不进行图学习则采用原始图计算
                cur_adj = self.adj0
                graphLoss_update_continue = False

            node_vec = torch.relu(self.model.encoder.graph_encoders[0](slideWindow_first_day_feature,cur_adj))  # GCN layer1 : Z(t) = ReLU(MP(A(t)_hat,MP(A(0),W1)))
            node_vec = F.dropout(node_vec, self.config.get('gl_dropout', 0), training=self.model.training)

            if self.config['idgl']['graph_learn'] and is_mean_curA:
                cur_adj = cur_adj.mean(0)

            t2m_pred = self.model.encoder.graph_encoders[-1](node_vec,cur_adj,feature)  # GCN layer2 : output=MP(A(1)_hat,MP(Z(1),W2))

            loss = loss + self.criterion(t2m_pred, t2m_label)

            if self.config['idgl']['graph_learn'] and self.config['idgl']['graph_learn_regularization'] and graphLoss_update_continue == True:
                graph_loss_adj = cur_raw_adj.mean(0)
                graph_loss_feature = slideWindow_first_day_feature.mean(0)
                loss = loss + self.add_graph_loss(graph_loss_adj, graph_loss_feature)

            # 每轮都进行存储
            if task_type == "train":

                if self.config['idgl']['graph_learn']:
                    self.cur_adj1 = cur_adj.clone().detach()
                    self.node_vec1 = node_vec.clone().detach()

                total_loss = loss.clone().detach() + total_loss.item()
                pth_idx += 1
                pth_idx_str = pth_idx_str + str(pth_idx) + ".pth"
                loss.backward()
                self.optimizer.step()
                torch.save(self.model.state_dict(),pth_idx_str)
                load_modelParam = True
                self.optimizer.zero_grad()

            if task_type == "val" or task_type == "test":
                total_loss = loss.clone().detach() + total_loss.item()
                load_modelParam = True

            if task_type == "test":
                t2m_pred_val = np.concatenate([t2m_hist.cpu().detach().numpy(), t2m_pred.cpu().detach().numpy()],axis=1) * self.t2m_std + self.t2m_mean
                t2m_label_val = t2m.cpu().detach().numpy() * self.t2m_std + self.t2m_mean
                self.predict_list.append(t2m_pred_val)
                self.label_list.append(t2m_label_val)
                self.time_list.append(timestamp_arr.cpu().detach().numpy())

        # 复制最后模型参数为Param0.pth
        if task_type == "train":
            # 绘邻接矩阵热点图
            if self.config['idgl']['graph_learn']:
                print('start imaging')
            else :
                print('start imaging')
                cur_add = 255 * cur_adj
                save_adj_new = "result/epoch=" + str(self.epoch_num) + "_adj.npy"
                np.save(save_adj_new, cur_add.cpu().detach().numpy())

            # 存储参数
            pth_new = "./save_train_param/Param0.pth"
            shutil.copyfile(pth_idx_str,pth_new)

        if task_type == "test":
            pth_new = "./save_train_param/Param0.pth"
            pth_save_final = "./save_final_Parameter/Param_new_final.pth"
            shutil.copyfile(pth_new,pth_save_final)

        if task_type == "val" or task_type=="test":
            total_loss = loss.clone().detach() + total_loss.item()

        if task_type == "test" :
            self.predict_epoch = np.concatenate(self.predict_list,axis=0)
            self.label_epoch = np.concatenate(self.label_list, axis=0)
            self.time_epoch = np.concatenate(self.time_list, axis=0)
            self.predict_epoch[self.predict_epoch < 0] = 0

        total_loss = total_loss.item() / (batch_idx + 1)

        return total_loss

    def add_graph_loss(self, out_adj, features):  # 输入 A(t) 和 features:X
        # Graph regularization
        graph_loss = 0
        L = torch.diagflat(torch.sum(out_adj, -1, keepdim=True)) - out_adj  # (2708,2708) diagflat对角扩展 L = D-A
        graph_loss += self.config['idgl']['smoothness_ratio'] * torch.trace(torch.mm(features.transpose(-1, -2), torch.mm(L, features))) / int(np.prod(out_adj.shape))  # Ω(A,X) = 1/n^2 tr(X^T L X) 最小化平滑损失 | tr() 表示对角线元素总和
        ones_vec = to_cuda(torch.ones(out_adj.size(-1)), self.device)
        graph_loss += -self.config['idgl']['degree_ratio'] * torch.mm(ones_vec.unsqueeze(0), torch.log(torch.mm(out_adj, ones_vec.unsqueeze(-1)) + VERY_SMALL_NUMBER)).squeeze() / out_adj.shape[-1]  # -β/n 1^T log(A1)
        graph_loss += self.config['idgl']['sparsity_ratio'] * torch.sum(torch.pow(out_adj, 2)) / int(np.prod(out_adj.shape))  # f(A) = ↑ + γ/n^2 ||A||_2_F
        return graph_loss  # loss_graph

    def get_loss_list(self):
        return self.train_loss_list,self.val_loss_list,self.test_loss_list


# -------------------------------------------------------------------------- #
# ---------------------------- Imported Modules ---------------------------- #

# General
import os

# PyTorch
import torch
import torch.nn as nn
# Plotting
import matplotlib
import matplotlib.pyplot as plt
import matplotlib.animation as manimation

# -------------------------------------------------------------------------- #
# --------------------------- Model Architecture --------------------------- #

class transformerEncoder(nn.Module):
    def __init__(self, embeddingDim, num_heads, numLayers):
        super(transformerEncoder, self).__init__()
        # General model parameters.
        self.embeddingDim = embeddingDim
        self.numLayers = numLayers
        self.num_heads = num_heads

        # Define the attention mechanism.
        self.attentionMechanism = nn.MultiheadAttention(
            num_heads = self.num_heads,   # Number of parallel attention heads. Note that embed_dim will be split across num_heads (i.e. each head will have dimension embed_dim // num_heads).
            embed_dim = embeddingDim,     # The embdedded dimension of the query.
            kdim = embeddingDim,    # Total number of features for keys. Default: None (uses kdim=embed_dim).
            vdim = embeddingDim,    # Total number of features for values. Default: None (uses vdim=embed_dim).
            batch_first = True,     # If True, then the input and output tensors are provided as (batch, seq, feature). Default: False (seq, batch, feature).
            add_bias_kv = True,     # If specified, adds bias to the key and value sequences at dim=0. Default: False.
            add_zero_attn = False,      # Appends zeros to the key and value sequences at dim=1 for size consitency. Default: False.
            dropout = 0.2,          # Dropout probability on attn_output_weights (commonly 0.1-0.3). Default: 0.0 (no dropout).
            bias = True,            # If specified, adds bias to input / output projection layers. Default: True.
        )

        # Add non-linearity to attention.
        self.feedForwardLayers = nn.Sequential(
            # It is common to expand the embeddingDim
                # By a factor of 2-4 (small),
                # By a factor of 4-8 (medium),
                # By a factor of 8-16 (large).

            # Neural architecture: Layer 1.
            nn.Linear(embeddingDim, 64, bias = True),
            nn.GELU(),
            nn.Dropout(0.2),

            # Neural architecture: Layer 2.
            # nn.Linear(64, 32, bias = True),
            # nn.GELU(),

            # Neural architecture: Layer 3.
            nn.Linear(64, embeddingDim, bias = True),
            nn.GELU(),
        )

        # Initialize the layer normalization.
        self.layerNorm_SA = nn.LayerNorm(embeddingDim, eps = 1E-10)
        self.layerNorm_FF = nn.LayerNorm(embeddingDim, eps = 1E-10)
        self.layerNorm_Final = nn.LayerNorm(embeddingDim, eps = 1E-10)

        # Initialize holder parameters.
        self.allAttentionWeights = []  # Dimension: numEpochs, numLayers, attentionWeightDim, where attentionWeightDim = batch_size, numHeads, seq_length, seq_length

    def forward(self, signalData, contextualData, allTrainingData = False):
        """
        The shape of signalData = (batchSize, numSignals, self.compressedLength)
        The shape of contextualData = (batchSize, numSignals, self.contextualLength - 1)
        """
        if allTrainingData: self.allAttentionWeights.append([]);

        # Calculate the size information of each tensor.
        batchSize, numSignals, compressedLength = signalData.size()
        batchSize, numSignals, contextualLength = contextualData.size()

        # Concatenate the signals with their context.
        contextAwareSignals = torch.zeros((batchSize, numSignals, compressedLength + contextualLength))
        contextAwareSignals[:, :, 0:compressedLength] += signalData
        contextAwareSignals[:, :, compressedLength:] += contextualData

        # For each encoding layer.
        for layerInd in range(self.numLayers):
            # Combine the values from the self attentuation block.
            selfAttentionData = self.selfAttentionBlock(contextAwareSignals, allTrainingData)
            contextAwareSignals = contextAwareSignals + selfAttentionData.clone()

            # Combine the values from the feed-forward block.
            feedForwardData = self.feedForwardBlock(contextAwareSignals) # Apply feed-forward block.
            contextAwareSignals = contextAwareSignals + feedForwardData.clone()

        # Final normalization after encoding.
        contextAwareSignals = self.layerNorm_Final(contextAwareSignals)

        return contextAwareSignals

    def selfAttentionBlock(self, signalData, allTrainingData):
        # Apply self attention block to the signals.
        normSignalData = self.layerNorm_SA(signalData)
        attentionOutput, attentionWeights = self.attentionMechanism(normSignalData, normSignalData, normSignalData,
                                                                    average_attn_weights = False, need_weights = True)
        if allTrainingData: self.allAttentionWeights[-1].append(attentionWeights[0:1])  # I am indexing 0:1 to only take the first batch due to memory constraints.

        return attentionOutput

    def feedForwardBlock(self, signalData):
        # Apply feed forward block to the signals.
        normSignalData = self.layerNorm_FF(signalData)
        outputANN = self.feedForwardLayers(normSignalData)

        return outputANN

    def visualizeAttention(self, modelInd, batchInd  = 0):
        if len(self.allAttentionWeights) == 0: return  None

        numPlots = self.num_heads*self.numLayers
        # Calculate the number of attention heads and sequence length
        numPlots_perRow = min(2, numPlots)
        num_rows = (numPlots + numPlots_perRow - 1) // numPlots_perRow

        movieTitle = "Visualization of Self-Attention"
        # Initialize Movie Writer for Plots
        metadata = dict(title=movieTitle, artist='Matplotlib', comment='Movie support!')
        writer = manimation.FFMpegWriter(fps=5, metadata=metadata)

        # Create subplots for each attention head
        fig, axes = plt.subplots(nrows=num_rows, ncols=numPlots_perRow, figsize=(15, 5*num_rows), sharex=True, sharey=True)
        flattenedAxes = axes.ravel() if numPlots != 1 else [axes]

        # Initialize image objects for each subplot
        image_objects = []
        for plotInd in range(numPlots):
            ax = flattenedAxes[plotInd]
            layerInd = plotInd//self.num_heads
            headInd = plotInd%self.num_heads

            # Get the colorbar boundaries.
            minVal = self.allAttentionWeights[0][0][batchInd].min().item()
            maxVal = self.allAttentionWeights[0][0][batchInd].max().item()

            # Add a plot for each head.
            im = ax.imshow(self.allAttentionWeights[0][0][batchInd, 0, :, :-1].detach().numpy(),
                           cmap='RdBu_r', interpolation='nearest', animated=True, origin='lower',
                           vmin=minVal, vmax=maxVal)
            image_objects.append(im)
            # Set figure information.
            ax.set_xlabel('Target Sequence Length')
            ax.set_ylabel('Source Sequence Length')
            ax.set_title(f'Attention Head {headInd+1} at Layer {layerInd+1}')

        # Add colorbar (created only once)
        cbar = fig.colorbar(image_objects[0], ax=flattenedAxes, shrink=0.4, aspect=5)
        cbar.ax.yaxis.set_major_formatter(matplotlib.ticker.ScalarFormatter())
        cbar.ax.set_ylabel('Attention Weight')

        # Save folder
        saveFolder = os.path.dirname(__file__) + "/../metaTrainingPlots/attentionWeights/"
        os.makedirs(saveFolder, exist_ok=True) # Create the folders if they do not exist.

        # Open the movie and add the data.
        with writer.saving(fig, saveFolder + movieTitle + f"_{modelInd}.mp4", 300):
            # For each training epoch.
            for epoch in range(len(self.allAttentionWeights)):
                # For each head at rach layer.
                for plotInd in range(numPlots):
                    layerInd = plotInd//self.num_heads
                    headInd = plotInd%self.num_heads
                    ax = flattenedAxes[plotInd]
                    im = image_objects[plotInd]

                    # Update the data in the image object
                    im.set_array(self.allAttentionWeights[epoch][layerInd][batchInd, headInd, :, :-1].detach().numpy())
                    fig.suptitle(f'Visualization of Self-Attention Weights: Epoch {epoch}')

                writer.grab_frame()

        # Clear plots
        plt.clf(); plt.close(fig)

Helper Files/Machine Learning/Model Control/Models/pyTorch Models/Model Architectures/_emotionModel/_modelComponents/transformerEncoder.py