from typing import Union, List, Dict

import pandas as pd
import requests
from requests import Response

class EETCDataClient:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.base_url = "https://eetc-data-hub-service-nb7ewdzv6q-ue.a.run.app/api"
        # TODO check API Key validity during __init__ & raise exception

    def _send_http_request(self, url: str, params: dict) -> Response:
        if params is None:
            params = {}

        response = requests.get(
            url,
            params=params,
            headers={"EETC-API-Key": self.api_key},
        )

        if response.status_code != 200:
            response.raise_for_status()

        return response

    def get_price_data(
        self,
        symbol: str,
        date: str = None,
        from_date: str = None,
        to_date: str = None,
        as_json=False,
    ) -> Union[pd.DataFrame, List[Dict]]:
        """
        Get historical Price data from EETC Data Hub via REST API.

        :param symbol: Symbol of the instrument.
        :param date: Specific date in string format "yyyy-mm-dd"
        :param from_date: Earliest date in string format "yyyy-mm-dd"
        :param to_date: Latest date in string format "yyyy-mm-dd"
        :param as_json: Indicates if caller wants data returned as JSON. False
        by default, if False, it will return the data as a pandas DataFrame.
        :return: Historical Price data as a pandas DataFrame.
        """

        url = f"{self.base_url}/price/?symbol={symbol}"
        params = {}

        # add optional query params
        if date:
            params["date"] = date

        if from_date:
            params["from_date"] = from_date

        if to_date:
            params["to_date"] = to_date

        # send the HTTP request to EETC Data Hub
        response = self._send_http_request(url, params)

        # process and return response data
        response_data = response.json()

        if as_json:
            return response_data

        df = pd.json_normalize(response_data)
        df = df.sort_values(by=["date"])

        return df

    def get_fundamentals_data(
        self,
        symbol: str,
        frequency: str = "Quarterly",
        name: str = None,
        year: int = None,
        as_json=False,
    ) -> Union[pd.DataFrame, List[Dict]]:
        """
        Get historical Fundamentals data from EETC Data Hub via REST API.

        :param symbol: Symbol of the instrument.
        :param frequency: Can be "Yearly" or "Quarterly".
        :param name: Name of the instrument/company.
        :param year: Specific year for which the caller wants data.
        :param as_json: Indicates if caller wants data returned as JSON. False
        by default, if False, it will return the data as a pandas DataFrame.
        :return: Historical Fundamentals data as a pandas DataFrame.
        """

        url = f"{self.base_url}/fundamentals/?symbol={symbol}&frequency={frequency}"
        params = {}

        # add optional query params
        if name:
            params["name"] = name

        if year:
            params["year"] = year

        # send the HTTP request to EETC Data Hub
        response = self._send_http_request(url, params)

        # process and return response data
        response_data = response.json()

        if as_json:
            return response_data

        return pd.json_normalize(response_data)

    def get_indicator_data(
        self,
        name: str,
        frequency: str = None,
        from_date: str = None,
        to_date: str = None,
        as_json=False,
    ) -> Union[pd.DataFrame, List[Dict]]:
        """
        Get historical Macroeconomic data from EETC Data Hub via REST API.

        :param name: Name of the macroeconomic data point.
        :param frequency: "Yearly", "Quarterly", "Monthly", "Weekly", "Daily".
        :param from_date: Earliest date in string format "yyyy-mm-dd"
        :param to_date: Latest date in string format "yyyy-mm-dd"
        :param as_json: Indicates if caller wants data returned as JSON. False
        by default, if False, it will return the data as a pandas DataFrame.
        :return: Historical Macroeconomic data as a pandas DataFrame.
        """

        url = f"{self.base_url}/indicators/?name={name}"
        params = {}

        # add optional query params
        if frequency:
            params["frequency"] = frequency

        if from_date:
            params["from_date"] = from_date

        if to_date:
            params["to_date"] = to_date

        # send the HTTP request to EETC Data Hub
        response = self._send_http_request(url, params)

        # process and return response data
        response_data = response.json()

        if as_json:
            return response_data

        df = pd.json_normalize(response_data)
        df = df.sort_values(by=["date"])

        return df

    def get_indicators(self) -> Dict[str, List[str]]:
        """
        Get supported indicators grouped by frequency from EETC Data Hub via
        REST API.

        :return: List of indicator names grouped by frequency.
        """

        url = f"{self.base_url}/indicators/names/"

        # send the HTTP request to EETC Data Hub
        response = self._send_http_request(url, {})

        # process and return response data
        response_data = response.json()

        return response_data

    def get_companies(self, index: str = None) -> Dict[str, List[str]]:
        """
        Get supported companies from EETC Data Hub via REST API.

        :param index: Index which contains the Company.
        :return: List of companies in the EETC Data Hub database.
        """

        url = f"{self.base_url}/companies/"
        params = {}

        # add optional query params
        if index:
            params["index"] = index

        # send the HTTP request to EETC Data Hub
        response = self._send_http_request(url, params)

        # process and return response data
        response_data = response.json()

        return response_data


# %%
import sqlite3
from pathlib import Path
from typing import Any, Dict, List

from graphnet.utilities.logging import get_logger
from icecube.constants import *

logger = get_logger(log_folder=log_dir)

import numpy as np
import pandas as pd
import torch
from pytorch_lightning.callbacks import (EarlyStopping, LearningRateMonitor,
                                         ModelCheckpoint)
from pytorch_lightning.loggers import WandbLogger
from pytorch_lightning.profiler import SimpleProfiler
from sklearn.model_selection import KFold
from torch.optim import SGD
from tqdm import tqdm

from graphnet.data.constants import FEATURES, TRUTH
from graphnet.models import StandardModel
from graphnet.models.detector.icecube import IceCubeKaggle
from graphnet.models.gnn import DynEdge
from graphnet.models.graph_builders import KNNGraphBuilder
from graphnet.models.task.reconstruction import \
    DirectionReconstructionWithKappa
from graphnet.training.callbacks import PiecewiseLinearLR, ProgressBar
from graphnet.training.labels import Direction
from graphnet.training.loss_functions import VonMisesFisher3DLoss
from graphnet.training.utils import make_dataloader

torch.set_float32_matmul_precision("high")

PULSEMAP = "pulse_table"
DATABASE_PATH = database_dir / "batch_51_100.db"
# DATABASE_PATH = "/media/eden/sandisk/projects/icecube/input/sqlite/batch_1.db"
PULSE_THRESHOLD = 400
SEED = 42

# Training configs
MAX_EPOCHS = 100
LR = 5e-4
MOMENTUM = 0.9
BS = 256
ES = 10
NUM_FOLDS = 5
NUM_WORKERS = 16

# Paths
FOLD_PATH = input_dir / "folds"
COUNT_PATH = FOLD_PATH / "batch51_100_counts.csv"
CV_PATH = FOLD_PATH / f"batch51_100_cv_max_{PULSE_THRESHOLD}_pulses.csv"
WANDB_DIR = log_dir
PROJECT_NAME = "icecube"
GROUP_NAME = "pretrain_sub_5_batch_51_100_large_resume"

CREATE_FOLDS = False

def make_selection(
    df: pd.DataFrame, num_folds: int = 5, pulse_threshold: int = 200
) -> None:
    """Creates a validation and training selection (20 - 80). All events in both selections satisfies n_pulses <= 200 by default."""
    n_events = np.arange(0, len(df), 1)
    df["fold"] = 0

    kf = KFold(n_splits=num_folds, shuffle=True, random_state=SEED)
    for i, (_, val_idx) in enumerate(kf.split(n_events)):
        df.loc[val_idx, "fold"] = i

    # Remove events with large pulses from training and validation sample (memory)
    df["fold"][df["n_pulses"] > pulse_threshold] = -1

    df.to_csv(CV_PATH)
    return

def get_number_of_pulses(db: Path, event_id: int, pulsemap: str) -> int:
    with sqlite3.connect(str(db)) as con:
        query = f"select event_id from {pulsemap} where event_id = {event_id} limit 20000"
        data = con.execute(query).fetchall()
    return len(data)

def count_pulses(database: Path, pulsemap: str) -> pd.DataFrame:
    """Will count the number of pulses in each event and return a single dataframe that contains counts for each event_id."""
    with sqlite3.connect(str(database)) as con:
        query = "select event_id from meta_table"
        events = pd.read_sql(query, con)
    counts = {"event_id": [], "n_pulses": []}

    for event_id in tqdm(events["event_id"]):
        a = get_number_of_pulses(database, event_id, pulsemap)
        counts["event_id"].append(event_id)
        counts["n_pulses"].append(a)

    df = pd.DataFrame(counts)
    df.to_csv(COUNT_PATH)
    return df

def build_model(
    config: Dict[str, Any], train_dataloader: Any
) -> StandardModel:
    """Builds GNN from config"""
    # Building model
    detector = IceCubeKaggle(
        graph_builder=KNNGraphBuilder(nb_nearest_neighbours=8),
    )
    gnn = DynEdge(
        nb_inputs=detector.nb_outputs,
        global_pooling_schemes=["min", "max", "mean"],
    )

    if config["target"] == "direction":
        task = DirectionReconstructionWithKappa(
            hidden_size=gnn.nb_outputs,
            target_labels=config["target"],
            loss_function=VonMisesFisher3DLoss(),
        )
        prediction_columns = [
            config["target"] + "_x",
            config["target"] + "_y",
            config["target"] + "_z",
            config["target"] + "_kappa",
        ]
        additional_attributes = ["zenith", "azimuth", "event_id"]

    model = StandardModel(
        detector=detector,
        gnn=gnn,
        tasks=[task],
        optimizer_class=SGD,
        optimizer_kwargs={
            "lr": LR,
            "momentum": MOMENTUM,
            "nesterov": True,
        },
        scheduler_class=PiecewiseLinearLR,
        scheduler_kwargs={
            "milestones": [
                0,
                len(train_dataloader) / 2,
                len(train_dataloader) * config["fit"]["max_epochs"],
            ],
            "factors": [1e-03, 1, 1e-03],
        },
        scheduler_config={
            "interval": "step",
        },
    )
    model.prediction_columns = prediction_columns
    model.additional_attributes = additional_attributes

    return model

def load_pretrained_model(
    config: Dict[str, Any],
    state_dict_path: str = "/kaggle/input/dynedge-pretrained/dynedge_pretrained_batch_1_to_50/state_dict.pth",
) -> StandardModel:
    train_dataloader, _ = make_dataloaders(config=config)
    model = build_model(config=config, train_dataloader=train_dataloader)
    # model._inference_trainer = Trainer(config['fit'])
    state_dict = torch.load(state_dict_path)["state_dict"]
    model.load_state_dict(state_dict)
    model.prediction_columns = [
        config["target"] + "_x",
        config["target"] + "_y",
        config["target"] + "_z",
        config["target"] + "_kappa",
    ]
    model.additional_attributes = ["zenith", "azimuth", "event_id"]
    return model

def make_dataloaders(config: Dict[str, Any], fold: int = 0) -> List[Any]:
    """Constructs training and validation dataloaders for training with early stopping."""
    df_cv = pd.read_csv(CV_PATH)

    val_idx = (
        df_cv[df_cv["fold"] == fold][config["index_column"]].ravel().tolist()
    )
    train_idx = (
        df_cv[~df_cv["fold"].isin([-1, fold])][config["index_column"]]
        .ravel()
        .tolist()
    )

    train_dataloader = make_dataloader(
        db=config["path"],
        selection=train_idx,
        pulsemaps=config["pulsemap"],
        features=FEATURES.KAGGLE,
        truth=TRUTH.KAGGLE,
        batch_size=config["batch_size"],
        num_workers=config["num_workers"],
        shuffle=True,
        labels={"direction": Direction()},
        index_column=config["index_column"],
        truth_table=config["truth_table"],
    )

    validate_dataloader = make_dataloader(
        db=config["path"],
        selection=val_idx,
        pulsemaps=config["pulsemap"],
        features=FEATURES.KAGGLE,
        truth=TRUTH.KAGGLE,
        batch_size=config["batch_size"],
        num_workers=config["num_workers"],
        shuffle=False,
        labels={"direction": Direction()},
        index_column=config["index_column"],
        truth_table=config["truth_table"],
    )

    return train_dataloader, validate_dataloader

def convert_to_3d(df: pd.DataFrame) -> pd.DataFrame:
    """Converts zenith and azimuth to 3D direction vectors"""
    df["true_x"] = np.cos(df["azimuth"]) * np.sin(df["zenith"])
    df["true_y"] = np.sin(df["azimuth"]) * np.sin(df["zenith"])
    df["true_z"] = np.cos(df["zenith"])
    return df

def calculate_angular_error(df: pd.DataFrame) -> pd.DataFrame:
    """Calcualtes the opening angle (angular error) between true and reconstructed direction vectors"""
    df["angular_error"] = np.arccos(
        df["true_x"] * df["direction_x"]
        + df["true_y"] * df["direction_y"]
        + df["true_z"] * df["direction_z"]
    )
    return df

# %%
config = {
    "inference_database_path": "/media/eden/sandisk/projects/icecube/input/sqlite/test_batch_641_660.db",
    "path": str(DATABASE_PATH),
    "pulsemap": "pulse_table",
    "truth_table": "meta_table",
    "features": FEATURES.KAGGLE,
    "truth": TRUTH.KAGGLE,
    "index_column": "event_id",
    "batch_size": BS,
    "num_workers": NUM_WORKERS,
    "target": "direction",
    "run_name_tag": "batch_1_50",
    "early_stopping_patience": ES,
    "fit": {
        "max_epochs": MAX_EPOCHS,
        "gpus": [0],
        "distribution_strategy": None,
        "limit_train_batches": 0.1,  # debug
        "limit_val_batches": 0.1,
    },
    "base_dir": "training",
    "wandb": {
        "project": PROJECT_NAME,
        "group": GROUP_NAME,
    },
    "lr": LR,
}

# %%
ckpt = "/media/eden/sandisk/projects/icecube/models/graphnet/ft_graphnet_50_100.ckpt"

# %%
run_name = f"dynedge_{config['target']}_{config['run_name_tag']}"

model = load_pretrained_model(config, state_dict_path=ckpt)

test_dataloader = make_dataloader(
    db = config['inference_database_path'],
    selection = None, # Entire database
    pulsemaps = config['pulsemap'],
    features = config["features"],
    truth = config["truth"],
    batch_size = config['batch_size'],
    num_workers = config['num_workers'],
    shuffle = False,
    labels = {'direction': Direction()},
    index_column = config['index_column'],
    truth_table = config['truth_table'],
)

# %%
from torchmetrics import Metric

class MeanAngularError(Metric):
    def __init__(self):
        super().__init__()
        self.add_state(
            "err",
            default=torch.tensor(0.0, dtype=torch.float32),
            dist_reduce_fx="sum",
        )
        self.add_state(
            "total",
            default=torch.tensor(0, dtype=torch.long),
            dist_reduce_fx="sum",
        )

    def update(self, preds: torch.Tensor, target: torch.Tensor):
        if preds.size(1) > target.size(1):
            preds = preds[:, : target.size(1)]

        assert (
            preds.shape == target.shape
        ), f"preds in size {preds.shape} doesn't match target in size {target.shape}"

        rt = torch.linalg.vector_norm(target, dim=-1, keepdim=True)
        rp = torch.linalg.vector_norm(preds, dim=-1, keepdim=True)

        target = target / rt
        preds = preds / rp

        err = torch.arccos(
            target[:, 0] * preds[:, 0]
            + target[:, 1] * preds[:, 1]
            + target[:, 2] * preds[:, 2]
        )

        err = torch.clip(err, 0, 2*torch.pi)

        self.err += err.sum()
        self.total += preds.size(0)

    def compute(self):
        return self.err.item() / self.total.item()

# %%
model = model.to("cuda").eval()
mae = MeanAngularError()

# %%
model.predict_as_dataframe(
    dataloader=test_dataloader,
    gpus=[0],
    prediction_columns=model.prediction_columns,
    additional_attributes=model.additional_attributes,
)

# %%


import pymysql
import numpy as np
import matplotlib.pyplot as plt
from dbase import DbConnect

db = pymysql.connect(host="localhost", user="pynalyze", passwd="", db="pz")
cursor = db.cursor()
X = 318
r = []
stmt = """select avg from feedback where t_id=%s and q_id=%s"""
for i in range(12):
    cursor.execute(stmt, (X, i+1))
    r.append(cursor.fetchone()[0])
cursor.execute("Select t_name from mt_teacher where t_id=(%s)",(X))
name = cursor.fetchone()[0]

plt.rcdefaults()

# from matplotlib.ticker import FormatStrFormatter
plt.tick_params(axis='both', which='major', labelsize=8)
plt.tick_params(axis='both', which='minor', labelsize=7)

objects = ('EXPLANATION', 'OPPORTUNITY', 'STIMULATION', 'SYLLABUS COMP.', 'TIME USAGE', 'PAPER CORRECTION',
           'COMM.', 'CLASS CONTROL', 'ATTITUDE', 'VICTIMIZATION', 'FAVOURITISM', 'PUNCTUAL')
y_pos = np.arange(len(objects))

performance = []
for i in range(12):
    performance.append(r[i])
print(performance)
bar = plt.bar(y_pos, performance, width=0.75, color='y', align='center', alpha=1.0)

bar[0].set_color('orange')
bar[1].set_color('blue')
bar[2].set_color('green')
bar[3].set_color('purple')
bar[4].set_color('red')
bar[5].set_color('brown')
bar[6].set_color('pink')
bar[7].set_color('grey')
bar[8].set_color('olive')
bar[9].set_color('black')
bar[10].set_color('yellow')
bar[11].set_color('cyan')

plt.xticks(y_pos, objects)
plt.ylabel('Ratings')
plt.title(name)
manager = plt.get_current_fig_manager()
# manager.window.showMaximized()
# plt.show()
plt.savefig(name+'.pdf', bbox_inches='tight')
plt.savefig(name+'.png', bbox_inches='tight')

#def graphical():


import requests
import os
from dotenv import load_dotenv
from bs4 import BeautifulSoup

#Function to prepare the names as paths:
cleanName= lambda e: e.lower().replace(' ','-').replace('.','').replace('&','and')\
               .replace('é','e').replace('ø','o').replace('\'','').replace('!','')\
                   .replace('*','').replace('$','s')

#Prepare APIKEY:
load_dotenv()
    # Load the apikey
apiKey = os.getenv("API_NAPSTER")

#Function to automate the requests:
def getFromNapster(art_path=None, url='', apiKey=apiKey):
    if art_path:
        # Construct the resource url
        url = f"https://api.napster.com/v2.2/artists/{art_path}"
    else: url=url
    # If apiKey is defined, pass a header
    headers = {"apikey":f"{apiKey}"} if apiKey else {}
    # Perform the request
    res = requests.get(url, headers=headers)
    # Extract json from body response
    return res.json()

#Function to get subrequests from the main request. Type must be 'artists' to get similar artists or 'genres' to get the genres
def getName(url, type):
    new_json = getFromNapster(url=url)
    return [x['name'] for x in new_json[type]]

#Funcion that uses the other functions to create an artist dictionary with info
def artist_dict(artist):
    json1 = getFromNapster(artist)
    #Some artists with non valid characters may be skipped
    if 'artists' in json1:
        if len(json1['artists'])==0:
            return None
    else: return None
    #Try the attributes in case they are not in the artist json
    if 'bios' in json1['artists'][0]:
        bio = BeautifulSoup(json1['artists'][0]['bios'][0]['bio'], 'html.parser').text
    else:    bio = None
    if 'blurbs' in json1['artists'][0]:
        blurb = json1['artists'][0]['blurbs']
    else: blurb = None
    if 'contemporaries' in json1['artists'][0]['links']:
        similars = getName(json1['artists'][0]['links']['contemporaries']['href'],'artists')
    else: similars = None
    if 'genres' in json1['artists'][0]['links']:
        genres = getName(json1['artists'][0]['links']['genres']['href'],'genres')
    else:   genres = None
    if 'images' in json1['artists'][0]['links']:
        images= json1['artists'][0]['links']['images']['href']
    else:   images = None
    return {'bio' : bio,
            'blurb' : blurb,
            'similars' : similars,
            'genres' : genres,
            'images' : images}


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

import logging
import os
import sys

from openfisca_core.scripts import build_tax_benefit_system
from openfisca_core.tools.test_runner import run_tests

def main(parser):
    args = parser.parse_args()
    logging.basicConfig(
        level=logging.DEBUG if args.verbose else logging.WARNING, stream=sys.stdout
    )

    tax_benefit_system = build_tax_benefit_system(
        args.country_package, args.extensions, args.reforms
    )

    options = {
        "pdb": args.pdb,
        "performance_graph": args.performance_graph,
        "performance_tables": args.performance_tables,
        "verbose": args.verbose,
        "aggregate": args.aggregate,
        "max_depth": args.max_depth,
        "name_filter": args.name_filter,
        "only_variables": args.only_variables,
        "ignore_variables": args.ignore_variables,
    }

    paths = [os.path.abspath(path) for path in args.path]
    sys.exit(run_tests(tax_benefit_system, paths, options))


#If the worker has three or more dependents, then an additional $35 is withheld to cover the extra cost of health insurance beyond what the employer pays.

#print purpose of program
print("Calculate taxes, dues, gross pay, and net pay based on hours and dependents given.")

repeat = "y"

while True:
  #prompt user for inputs
  salary = float(input("Enter salary per hour: "))
  ov_salary = float((salary*1.50))
  hours = float(input("Number of hours worked in a week: "))
  #if loop to check if overtime
  if hours > 40:
    ov_hours = abs(hours-40)
    hours = 40
  else:
    ov_hours = 0
  dep_number = float(input("Number of dependents: "))

  #print regular hours and overtime
  print("Regular hours:", format(hours, '.2f'), "(at $"+str(format(salary,'.2f')), "per hour)")
  print("Overtime hours:", format(ov_hours, '.2f'), "(at $"+str(format(ov_salary,'.2f')), "per hour)")
  print("Total hours:", format(hours, ".2f"))

  #calculate and print gross pay
  gross = float((salary*hours)+(ov_salary*ov_hours))
  print("Gross pay: $"+format(gross,'.2f'))

  #calculate and print social security
  ss_tax = (gross*6)/100
  print("Social Security tax: $"+format(ss_tax,'.2f'))

  #calculate and print federal taxes
  fed_tax = (gross*14)/100
  print("Federal tax: $"+format(fed_tax,'.2f'))

  #calculate and print state taxes
  st_tax = (gross*5)/100
  print("State tax: $"+format(st_tax,'.2f'))

  #print union dues
  print("Union dues: $"+format(10,'.2f'))

  #check dependents
  if dep_number >= 3:
    dep_fee = float(35)
    print("Family health insurance: $"+format(dep_fee, ".2f"))
  else:
    dep_fee = float(0)

  #calculate and print total deductions
  total = float(ss_tax)+float(fed_tax)+float(st_tax)+10+dep_fee
  print("Total deductions: $"+format(total,'.2f'))

  #calculate and print net pay
  if total > gross:
    net = float(gross)-float(total)
    print("Dues and insurance obligations outstripped pay by $"+str(format(net,'.2f')))
  else:
     net = float(gross)-float(total)
     print("Net pay: $"+format(net,'.2f'))

  #ask user if they would like to repeat

  repeat = input("Would you like to calculate another week's pay? (y/n) ")
  if repeat=="n":
    break


# 分离数据集
from pandas import read_csv
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression

# 导入数据
filename='pima_data.csv'
names= ['preg', 'plas', 'pres', 'skin', 'test', 'mass', 'pedi', 'age', 'class']
data = read_csv(filename, names=names)

# 将数据分为输入数据和输出结果
array = data.values
X = array[:, 0:8]
Y = array[:, 8]
test_size = 0.33
seed = 4
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=test_size, random_state=seed)
model = LogisticRegression(max_iter=200)
model.fit(X_train, Y_train)
result = model.score(X_test, Y_test)
print("算法评估结果：%0.3f%%" % (result * 100))

# My
import numpy as np
preresult = model.predict(X_test)
Y_test_ravel = Y_test.ravel()  # 将多维数组转换为一维数组
cv = np.mean(Y_test_ravel == preresult)
print(cv)


# This Method only works when we are given that majority element do exist in the array
# otherwise this method won't work
def findCandidate(A):
    maj_index = 0
    count = 1
    for i in range(1, len(A)):
        if A[maj_index] == A[i]:
            count += 1
        else:
            count -= 1
        print("(i=%s, count=%s)" % (i, count))
        if count == 0:
            maj_index = i
            count = 1
    return A[maj_index]

print(findCandidate([1, 1, 1, 2, 2, 2, 2]))


def load_graph(filehandle):
    graph = {}
    for line in filehandle.readlines():
        line = line.strip('\n').split()
        split = [l.split(',') for l in line[1:]]
        graph[int(line[0])] = [(int(u), int(v)) for u, v in split]
    return graph

def print_graph(graph):
    for vertex, edges in graph.items():
        print(vertex, edges)

def dijkstra(graph, source, num_verticies, infinity):
    """ Dijkstra's shortest-path algorithm """

    processed_vertices = {source}
    shortest_path = [infinity] * num_verticies
    shortest_path[source] = 0

    while len(processed_vertices) < (num_verticies - 1):

        # pick edge in frontier which minimises len[v] + length
        weight_next = infinity
        for v in processed_vertices:
            for vertex_weight in graph[v]:
                if vertex_weight[0] not in processed_vertices:
                    if (shortest_path[v] + vertex_weight[1]) < weight_next:
                        weight_next = shortest_path[v] + vertex_weight[1]
                        vertex_start = v
                        vertex_next = vertex_weight[0]

        shortest_path[vertex_next] = weight_next
        processed_vertices.add(vertex_next)
    print(processed_vertices)
    return shortest_path

if __name__ == '__main__':
    filehandle = open('data/course_2_assignment_2.txt')
    graph = load_graph(filehandle)
    # print_graph(graph)

    source = 1
    infinity = 1000000
    num_verticies = 201

    shortest_path = dijkstra(graph, source, num_verticies, infinity)
    print(shortest_path)
    # distances required to nodes:
    distances = []
    for node in (7,37,59,82,99,115,133,165,188,197):
        distances.append(shortest_path[node])
    answer = ''
    for d in distances:
        answer += str(d)
        answer += ','
    print('Answer', answer)


class Transaction:
	def __init__(self, line):
		values = line.split(',')
		self.user = values[0]
		self.chain = values[1]
		self.dept = values[2]
		self.category = values[3]
		self.company = values[4]
		self.brand = values[5]
		self.date = values[6]
		self.productsize = values[7]
		self.productmeasure = values[8]
		self.purchasequantity = values[9]
		self.purchaseamount = values[10]

	@classmethod
	def getTransactions(cls,count = 100, filename = 'data/transactions.csv'):

		transactions = []
		for e, line in enumerate(open(filename, 'r')):
			if(e == 0):
				continue
			if(e > count):
				break
			transactions.append(Transaction(line))
		return transactions


from django import forms

class input_form(forms.Form):
    position = forms.CharField(label='Position', max_length=100)
    location = forms.CharField(label='Location', max_length=100)

    def clean(self):
         cleaned_data = super(input_form, self).clean()
         position = cleaned_data['position']
         location = cleaned_data['location']
         if not position and not location:
            raise forms.ValidationError('You have to write something!')


from . import mqtt

#Allow the thread to restart after any interruptions
def localapp_thread():
    while True:
        try:
            run_localapp()
        except BaseException as e:
            print('{!r}; restarting thread'.format(e))

#Initialize our mqtt client
client = mqtt.initialize()

def run_localapp():

    #Uncomment this code to utilize the functions which import data from csv files into the database (may not work for your files)
    #from data.interface import csv_to_sql, csv_to_sql_harvest_data, csv_to_sql_temp_data, update_temp_file, csv_to_sql_harvest_data
    #Add plant attributes into database
    #csv_to_sql()
    #Add sensor data into database and update file table
    #csv_to_sql_temp_data()
    #update_temp_file()
    #csv_to_sql_harvest_data()

    #Connect our mqtt client
    mqtt.connect(client)

    #Subscribe client to relevant topics
    mqtt.subscribe(client)

    #Tell the client to listen
    mqtt.update(client)


from terminaltables import AsciiTable
import fetch_average_super_job_salary, fetch_average_head_hunter_salary
from dotenv import dotenv_values

def print_table(average_salaries, table_name):
    title = table_name
    table_headers = [
        ['Язык программирования', 'Вакансий найдено', 'Вакансий обработано', 'Средняя зарплата'],
    ]
    for average_salary in average_salaries:
        table_headers.append([average_salary, average_salaries[average_salary]['found_vacancies'],
                              average_salaries[average_salary]['processed_vacancies'],
                              average_salaries[average_salary]['average_salary']], )
    table_instance = AsciiTable(table_headers, title)
    for _ in range(4): table_instance.justify_columns[_] = 'center'
    print(table_instance.table)
    print()

def main():
    config = dotenv_values(".env")
    super_job_average_salaries = fetch_average_super_job_salary.get_salary_information_by_languages(config.get('SECRET_KEY_SUPER_JOB'))
    head_hunter_average_salaries = fetch_average_head_hunter_salary.get_salary_information_by_languages(config.get('EMAIL'))
    print_table(super_job_average_salaries, f'Super Job Moscow')
    print_table(head_hunter_average_salaries, f'Head Hunter Moscow')

if __name__ == '__main__':
    main()


#%matplotlib widget

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

from include.coordinates import to_utm, utm_distance
from include.rotation import  get_azimuth, reorientation

# change pyplot style
plt.style.use('bmh')

def sma_filter(l, w=25):
	return np.convolve(l, np.ones((w,))/w, mode='valid')

def median_filter(l, w=51):
	return scipy.signal.medfilt(l, w)

def pm_180(l):
	""" Change range from [0,360) to [-180,180] """
	return np.array([ v if v<=180 else v-360 for v in l ])

# read sensor data from a smartphone with the Y axis
# rotated 90º CCW with respect to the the vehicle's
data = pd.read_csv('data.csv.gz')

easting, northing, znumber, zletter = to_utm(
	data['latitude' ][::50].values,  # GPS reports one sample per second
	data['longitude'][::50].values
)

distance = utm_distance(easting, northing)

sc = plt.scatter(
	easting,
	northing,
	c=data['speed'][::50] *3.6 # convert speed from m/s to km/h, one sample per second
)
cbar = plt.colorbar(sc)
cbar.ax.set_ylabel('Speed (km/h)', rotation=90)
plt.title('Vehicle Trajectory \n (%.3f km, %.2f s)'%(distance/1000.0, len(data['latitude' ])/50.0) )
plt.ylabel('Northing (m)')
plt.xlabel('Easting (m)\n' + 'WGS84' +' '+ str(znumber) +' '+ zletter)
plt.show()

# calculate azimuth from accelerometer and magnetomer readings, considering magnetic declination
azimuth = get_azimuth(
	data['acc_x'], data['acc_y'], data['acc_z'],
	data['mag_x'], data['mag_y'], data['mag_z'],
	data['declination']
)
azimuth = median_filter(azimuth)

bearing = median_filter( data['bearing'])
bearing = pm_180(bearing)

# yaw is estimated as the difference between GPS reported direction of travel and azimuth
yaw = bearing - azimuth
yaw = pm_180(yaw)
median_yaw = np.median(yaw)

t = np.linspace(0, len(azimuth)/50.0, len(azimuth))

plt.title('Estimated Yaw')
plt.plot( t, yaw, label='Yaw')
plt.plot( t, [median_yaw]*len(azimuth), label='Median (%.2fº)'%(median_yaw) )
plt.ylabel('Estimated Yaw (degrees)')
plt.xlabel('Time (s)')
plt.legend()
plt.show()

r = reorientation(data['acc_x'], data['acc_y'], data['acc_z'], np.radians(median_yaw) )

acc_x = sma_filter(r[:,0])
acc_y = sma_filter(r[:,1])
acc_z = sma_filter(r[:,2])
speed = sma_filter(data['speed'])

t = np.linspace(0, len(acc_x)/50.0, len(acc_x))

plt.title('Reoriented Acceleration')
plt.plot(t, acc_x, label='Acc_x (m/s^2)')
plt.plot(t, acc_y, label='Acc_y (m/s^2)')
plt.plot(t, acc_z, label='Acc_z (m/s^2)')
plt.plot(t, speed, label='Speed (m/s)', linewidth=3)
plt.xlabel('Time (s)')
plt.ylabel('Units')
plt.legend(loc='upper left')
plt.show()


MENU = {
    "espresso": {
        "ingredients": {
            "water": 50,
            "coffee": 18,
            "milk": 0,
        },
        "cost": 1.5,
    },
    "latte": {
        "ingredients": {
            "water": 200,
            "milk": 150,
            "coffee": 24,
        },
        "cost": 2.5,
    },
    "cappuccino": {
        "ingredients": {
            "water": 250,
            "milk": 100,
            "coffee": 24,
        },
        "cost": 3.0,
    }
}

resources = {
    "water": 300,
    "milk": 200,
    "coffee": 100,
    "money": 0,
}

COINS = {
    'quarters': 0.25,
    'dimes': 0.10,
    'nickels': 0.05,
    'pennies': 0.01,
}

def report():
    output = f'''Water: {resources['water']}ml
Milk: {resources['milk']}ml
Coffee: {resources['coffee']}g
Money: ${resources['money']:.2f}
'''
    print(output)

def resources_sufficient(command):
    if resources['water'] < MENU[command]['ingredients']['water']:
        output = (False, 'water')
    elif resources['milk'] < MENU[command]['ingredients']['milk']:
        output = (False, 'milk')
    elif resources['coffee'] < MENU[command]['ingredients']['coffee']:
        output = (False, 'coffee')
    else:
        output = True
    return output

def update_resources(coffee):
    for ing in ['water', 'milk', 'coffee']:
        resources[ing] -= MENU[coffee]['ingredients'][ing]
    resources['money'] += MENU[coffee]['cost']

def process_payment(coffee):
    print("Please insert coins.")
    total = 0
    for coin, value in COINS.items():
        total += int(input(f'how many {coin}?:')) * value
    total -= MENU[coffee]['cost']
    if total >= 0:
        print(f"Here is ${total:.2f} in change.")
        print(f"Here is your {coffee} ☕. Enjoy!")
    else:
        print("Sorry, that's not enough money. Money refunded.")
    update_resources(coffee)

def transaction(item_name):
    resource_check = resources_sufficient(item_name)
    if resource_check == True:
        process_payment(item_name)
    else:
        print(f"Sorry, there is not enough {resource_check[1]}")

commands = ["espresso", "latte", "cappuccino", "report", "off"]
current_command = ''
while True:
    current_command = input(' What would you like? (espresso/latte/cappuccino):')
    if current_command not in commands:
        continue
    if current_command == 'off':
        break
    elif current_command == 'report':
        report()
    else:
        transaction(current_command)


def solve(n,m,A,B):
    C = [[0] * m for _ in range(n)] #[0]얘는 갑자기 왜 튀어나옴?
    for i in range(n):
        for j in range(m):
            C[i][j] = A[i][j] + B[i][j]
    return C

N,M = map(int, input().split()) #옆으로 나란히 입력받는거?
A = [list(map(int, input().split())) for _ in range(N)] #이렇게 for 다음에 _ 띄어서 적는 이유는?
B = [list(map(int, input().split())) for _ in range(N)]
C = solve(N,M,A,B)

for i in range(N):
    print(" ".join(map(str,C[i]))) #join은 무엇?


from rest_framework import serializers
from .models import Invoice, Bill, OwnerCharge
from contracts.serializers import ContractSerializer
from notices.serializers import MemoSerializer

class OwnerChargeSerializer(serializers.ModelSerializer):
    class Meta:
        model = OwnerCharge
        exclude = (
            "created_at",
            "updated_at",
        )

class BillListSerializer(serializers.ModelSerializer):
    class Meta:
        model = Bill
        fields = (
            "pk",
            "__str__",
            "start_date",
            "bill_date",
        )

class BillDetailSerializer(serializers.ModelSerializer):
    owner_charge = OwnerChargeSerializer(many=True, read_only=True)
    memos = MemoSerializer(many=True, read_only=True)

    class Meta:
        model = Bill
        exclude = (
            "created_at",
            "updated_at",
        )

class InvoiceListSerializer(serializers.ModelSerializer):
    bill = BillListSerializer(read_only=True)
    contract = ContractSerializer(read_only=True)

    class Meta:
        model = Invoice
        fields = (
            "pk",
            "is_payed",
            "bill",
            "__str__",
            "contract",
        )

class InvoiceDetailSerializer(serializers.ModelSerializer):
    bill = BillDetailSerializer(read_only=True)
    contract = ContractSerializer(read_only=True)

    class Meta:
        model = Invoice
        exclude = (
            "created_at",
            "updated_at",
        )


class Role:
    def __init__(self, name, weapon, hp=500, mp=300):
        self.name = name
        self.weapon = weapon
        self.hp = hp
        self.mp = mp

class Weapon:
    def __init__(self, wname, strength, type):
        self.wname = wname
        self.strength = strength
        self.type = type

if __name__ == '__main__':
    ji = Weapon('方天画戟', 100, '物理')
    print(ji.wname, ji.strength, ji.type)
    lb = Role('吕布', ji)
    print(lb.weapon.wname, lb.weapon.strength, lb.weapon.type)