from matplotlib import markers
import numpy as np
from datetime import datetime
import alpaca_trade_api as alpaca
from alpaca_trade_api.rest import TimeFrame
import pandas as pd
from secrets import API_KEY_ID, SECRET_KEY
from pandas.core.frame import DataFrame
import mplfinance as mpf
import csv
import os

class Bot:
    api = alpaca.REST(API_KEY_ID, SECRET_KEY)
    sym = ''
    slow_period = 40
    fast_period = 15
    stock_data = pd.DataFrame()
    transactions = pd.DataFrame({
        "price": [],
        "buy": [],
        "balance": [],
        "volume": []
    }, index=[])
    state = 0
    balance_history = pd.DataFrame()
    init_stock_closing = -1

    def __init__(self, sym, initial_balance):
        self.transactions.index.name = 'timestamp'
        self.sym = sym
        self.initial_balance = initial_balance
        self.funds = initial_balance
        self.min_balance = initial_balance
        self.min_funds = initial_balance
        self.holding = {
            'close': 0,
            'volume': 0,
            'timestamp': '',
        }
        now = datetime.now()
        self.init_datetime = now
        self.datadir =  "data/{0}_{1}-{2}-{3}".format(self.sym, now.year, now.month, now.day)

    def get_balance(self):
        return self.funds + (self.holding['close'] * self.holding['volume'])

    def add_to_stockdata(self, data):
        if len(self.stock_data.index) > self.slow_period*4:
            self.stock_data = self.stock_data.tail(self.slow_period*4).append(data)
        else:
            self.stock_data = self.stock_data.append(data)

    def add_to_transactions(self, order):
        if len(self.transactions.index) > self.slow_period*4:
            self.transactions = self.transactions.tail(self.slow_period*4).append(order)
        else:
            self.transactions = self.transactions.append(order)

    def is_holding(self):
        if self.holding['volume'] > 0:
            return True
        return False

    def print_order(self, order):
        order_type = '[BUY]' if order['buy'].values == 1 else '[SELL]'
        datetimeind = pd.DatetimeIndex(order.index)[0]
        order['datetime_pretty'] = '{0}/{1}/{2} {3}:{4}'.format(
            datetimeind.month,
            datetimeind.day,
            datetimeind.year,
            datetimeind.hour,
            datetimeind.minute
        )
        print(order_type + ' {0} - {1}x {2} at price ${3}'.format(order['datetime_pretty'].values[0], order['volume'].values[0], self.sym, order['price'].values[0] // 0.01 / 100))

    def get_transactions_filename(self):
        return '{4}/{0}_transactions_{1}-{2}-{3}.csv'.format(self.sym, self.init_datetime.year, self.init_datetime.month, self.init_datetime.day, self.datadir)

    def save_transaction(self, order):
        file = open(self.get_transactions_filename(), 'a')
        writer = csv.writer(file)
        writer.writerow([
            order.index.values[0],
            order['buy'].values[0],
            order['balance'].values[0],
            order['price'].values[0],
            order['volume'].values[0],
        ])
        file.close()
        return

    def get_all_transactions(self):
        filename = self.get_transactions_filename()
        df = pd.DataFrame()
        try:
            f = open(filename, "r")
        except:
            # no transactions were made
            return pd.DataFrame({
                'buy': [],
                'balance': [],
                'price': [],
                'volume': [],
            }, index=[])
        csvFile = csv.reader(f)
        for line in csvFile:
            row = pd.DataFrame({
                'buy': int(line[1]),
                'balance': float(line[2]),
                'price': float(line[3]),
                'volume': float(line[4]),
            }, index=[line[0]])
            df = df.append(row)
        f.close()
        return df

    def buy(self, shares, data):
        if self.is_holding():
            print('[ERROR] Cannot buy. Already holding {0}'.format(self.sym))
            return

        self.funds = self.funds - (shares * data['close'])
        self.holding['close'] = data['close']
        self.holding['volume'] = shares
        self.holding['timestamp'] = data.name
        buy_order = DataFrame([[1, self.get_balance(), data['close'], shares]], columns=['buy', 'balance', 'price', 'volume'], index=[data.name])
        self.add_to_transactions(buy_order)
        self.save_transaction(buy_order)
        self.print_order(buy_order)

    def sell(self, shares, data):
        if not self.is_holding():
            print("[ERROR] Cannot buy. Not holding any {0}".format(self.sym))

        self.funds = self.funds + (shares * data['close'])
        self.holding['close'] = 0
        self.holding['volume'] = 0
        self.holding['timestamp'] = ''

        sell_order = DataFrame([[0, self.get_balance(), data['close'], shares]], columns=['buy', 'balance', 'price', 'volume'], index=[data.name])
        self.add_to_transactions(sell_order)
        self.save_transaction(sell_order)
        self.print_order(sell_order)

    def tema_strategy(self):
        last_two = self.stock_data.tail(2)
        current = last_two.tail(1)
        previous = last_two.head(1)
        current_price = current['close'].values[0]

        # derivatives = pd.DataFrame()
        # derivatives['dTEMA'] = (self.stock_data['TEMA'].shift(periods=-1) - self.stock_data['TEMA'].shift(periods=1)) / (self.stock_data['TEMA'].shift(periods=-1) + self.stock_data['TEMA'].shift(periods=1))

        # if abs(derivatives.loc[previous.index]['dTEMA'].values[0] <= 10**(-7)) and not self.is_holding():
        #     return 1
        # elif abs(derivatives.loc[previous.index]['dTEMA'].values[0] <= 10**(-7)) and self.is_holding():
        #     return 0
        # return -1

        if current['TEMA'].values > current_price and not self.is_holding():
            return 1
        elif current['TEMA'].values < current_price and self.is_holding():
            return 0
        return -1

    def ewa_strategy(self):
        last_two = self.stock_data.tail(2)
        current = last_two.tail(1)
        previous = last_two.head(1)
        if previous['fast_EWA'].values < previous['slow_EWA'].values and current['fast_EWA'].values > current['slow_EWA'].values:
            return 0
        elif previous['fast_EWA'].values > previous['slow_EWA'].values and current['fast_EWA'].values < current['slow_EWA'].values:
            return 1
        return -1

    def make_decision(self, data):
        if self.init_stock_closing == -1:
            self.init_stock_closing = data['close']
        # Update holding
        if self.is_holding():
            self.holding['close'] = data['close']

        # Append data and calulate EWA
        self.add_to_stockdata(data)
        self.stock_data['slow_EWA'] = self.stock_data['close'].rolling(window=self.slow_period).mean()
        self.stock_data.loc[:self.slow_period, 'slow_EWA'] = np.nan
        self.stock_data['fast_EWA'] = self.stock_data['close'].ewm(span=self.fast_period, adjust=True).mean()
        self.stock_data.loc[:self.fast_period, 'fast_EWA'] = np.nan

        emas = pd.DataFrame()
        emas['EMA'] = self.stock_data['close'].rolling(window=10).mean()
        emas['EMA_1'] = emas['EMA'].rolling(window=10).mean()
        emas['EMA_2'] = emas['EMA_1'].rolling(window=10).mean()
        emas['EMA_3'] = emas['EMA_2'].rolling(window=10).mean()
        self.stock_data['TEMA'] = (3*emas["EMA_1"]) - (3*emas['EMA_2']) + emas['EMA_3']

        # Check it was appended
        current_price = self.stock_data.loc[data.name]['close']
        if not current_price == data['close']:
            print('Could not add data to list')
            return

        tema_res = self.tema_strategy()
        ewa_res = self.ewa_strategy()
        should_buy = -1
        if tema_res == ewa_res:
            should_buy = tema_res

        self.save_stock_record(self.stock_data.tail(1))
        # BUY
        if should_buy == 1 and not self.is_holding():
            if data['close'] >= self.funds:
                return
            shares = self.funds // data['close']
            self.buy(shares, data)
        # SELL
        elif should_buy == 0 and self.is_holding():
            bought_price = self.transactions.tail(1)['price'].values[0]
            shares = self.transactions.tail(1)['volume'].values[0]
            if data['close'] > bought_price*(1 + 0.02) or data['close'] <= bought_price*0.98:
                self.sell(shares, data)

        self.balance_history = self.balance_history.append(pd.DataFrame({
            "balance": self.get_balance(),
        }, index=[data.name]))

        if self.get_balance() < self.min_balance:
            self.min_balance = self.get_balance()
        if self.funds < self.min_funds:
            self.min_funds = self.funds

    def print_account(self):
        print("----- Account Information -----")
        print('Initial balance: ${0}'.format(self.initial_balance))
        print('Current funds: ${0}'.format(round(self.funds, 2)))
        print('Current balance: ${0}'.format(round(self.get_balance(), 2)))
        if self.is_holding():
            print('Total assets: {0}x {1} at ${2} (${3})'.format(self.holding['volume'], self.sym, self.holding['close'], self.holding['volume']*self.holding['close'] // 0.01 / 100))
        diff = (self.get_balance() - self.initial_balance)
        if  diff < 0:
            print('Account is down ${0} (%{1})'.format(diff // 0.01 / 100, (diff / self.initial_balance) // 0.01 / 100))
        elif diff > 0:
            print('Account is up ${0} (%{1})'.format(diff // 0.01 / 100, (diff / self.initial_balance) // 0.01 / 100 ))
        print("Minimum balance (%{0}): ${1}".format(round(self.min_balance / self.initial_balance * 100, 2), round(self.min_balance, 2)))
        print("Minimum funds (%{0}): ${1}".format(round(self.min_funds / self.initial_balance * 100, 2), round(self.min_funds, 2)))

    def run_test(self, start_date, end_date, timeframe):
        print("Getting data from alpaca...")
        data = self.api.get_bars(self.sym, timeframe, start_date, end_date).df
        data = data.filter(['close', 'open', 'volume', 'high', 'low'])
        print("Data received.")

        if not os.path.isdir(self.datadir):
            os.mkdir(self.datadir)
        if os.path.exists(self.get_stock_filename()):
            os.remove(self.get_stock_filename())
        if os.path.exists(self.get_transactions_filename()):
            os.remove(self.get_transactions_filename())

        start = datetime.now()
        for t, row in data.iterrows():
            self.make_decision(row)
        end = datetime.now()
        transactions = self.get_all_transactions()

        print('Elapsed time: {0}s'.format((end-start).total_seconds()))
        print('{0} trades were made'.format(len(transactions.index)))
        print()
        self.print_account()

        try:
            diff = bot.stock_data.tail(1)['close'][0] - bot.init_stock_closing
            diff = diff // 0.01 / 100
            init_volume = bot.transactions.head(1)['volume'][0]
            print("Net gain {0}: ${1} (${2})".format(self.sym, diff, diff*init_volume // 0.01 / 100))
        except:
            print("No transactions were made")

        print("Total decision duration: {0}".format(self.total_decision_time))
        return

    def get_all_stockdata(self):
        filename = self.get_stock_filename()
        df = pd.DataFrame()
        f = open(filename, "r")
        csvFile = csv.reader(f)
        for line in csvFile:
            row = pd.DataFrame({
                'close': float(line[1]),
                'open': float(line[2]),
                'high': float(line[3]),
                'low': float(line[4]),
                'volume': float(line[5]),
                'slow_EWA': float(line[6]),
                'fast_EWA': float(line[7]),
                'TEMA': float(line[8])
            }, index=[line[0]])
            df = df.append(row)
        f.close()
        return df

    def plot(self, candle = False):
        stock_data = self.get_all_stockdata()
        transactions = self.get_all_transactions()
        s = mpf.make_mpf_style(base_mpf_style='yahoo', rc={'font.size': 6})
        balance = mpf.make_addplot(self.balance_history,ylabel='Balance', width=2, panel=0)
        slow = mpf.make_addplot(stock_data['slow_EWA'], panel=1, width=0.5, color='purple')
        fast = mpf.make_addplot(stock_data['fast_EWA'], panel=1, width=0.5, linestyle='--', color='purple')
        close = mpf.make_addplot(stock_data['close'], panel=1, width=1, color='blue')

        tema = mpf.make_addplot(stock_data['TEMA'], panel=1, width=1, color='pink')

        temp = stock_data.filter(['close'])
        temp.index = pd.to_datetime(temp.index).tz_localize('Etc/UCT')
        buy_orders = transactions[transactions['buy'] == 1]
        buy_orders.index = pd.to_datetime(buy_orders.index)

        buys = temp.merge(buy_orders, how='outer', left_index=True, right_index=True)
        bought = mpf.make_addplot(buys['price'], panel=1, color='green', width=5, scatter=True, marker='^')

        sell_orders = transactions[transactions['buy'] == 0]
        sells = temp.merge(sell_orders, how='outer', left_index=True, right_index=True)
        sold = mpf.make_addplot(sells['price'], panel=1, color='red', width=5, scatter=True, marker='v')
        stock_data.index = pd.to_datetime(stock_data.index)

        type = None
        if candle:
            type = 'candle'
        else:
            type = 'line'
        figure, axes = mpf.plot(stock_data, type=type, panel_ratios=(0.3, 1, 0.3),
            volume=True,
            title=self.sym,
            style=s,
            figsize=(10,5),
            returnfig=True,
            addplot=[balance,slow,fast, bought, sold, close, tema],
            main_panel=1,
            volume_panel=2,
            num_panels=3
        )

        for t, b in buys.iterrows():
            axes[1].text(b.name, b.price, "${0}".format(b.price), color='black', zorder=9)

        axes[0].yaxis.set_label_position("left")
        axes[0].yaxis.tick_left()
        axes[4].yaxis.set_label_position("left")
        axes[4].yaxis.tick_left()
        mpf.show()

    def get_stock_filename(self):
        return '{4}/{0}_stockdata_{1}-{2}-{3}.csv'.format(self.sym, self.init_datetime.year, self.init_datetime.month, self.init_datetime.day, self.datadir)

    def save_stock_record(self, data):
        filename = self.get_stock_filename()
        file = open(filename, 'a')
        writer = csv.writer(file)
        writer.writerow([
            data.index.values[0],
            data['close'].values[0],
            data['open'].values[0],
            data['high'].values[0],
            data['low'].values[0],
            data['volume'].values[0],
            data['slow_EWA'].values[0],
            data['fast_EWA'].values[0],
            data['TEMA'].values[0]
        ])
        file.close()
        return

start_date = "2020-01-01"
end_date = "2020-01-30"
timeframe = TimeFrame.Minute

bot = Bot("F", 1000)
bot.run_test(start_date, end_date, timeframe)
stock_data = bot.get_all_stockdata()
#bot.plot()


import fasttext
import unicodedata
import re
from .database import ModelType
import os
import spacy

nlp = spacy.load("es_core_news_sm")

class NLPEngine:
    """NLP Engine
    A custom class to encapsulate a fasttext model.

    Attributes:
        :param @model_url: Name of the model
    """
    model = None

    def __init__(self, model_url):
        """
        Args:
            :param @model_url: Name of the model
        """
        try:
            self.model_url = os.path.dirname(__file__) + "/nlp_models/" + model_url
            self.model = fasttext.load_model(self.model_url)
        except Exception as e:
            print(e)
            print("Error")
            path = os.path.dirname(__file__) + "/nlp_models"
            if not os.path.exists(path):
                os.makedirs(path)
                print("Models must be installed")

    @staticmethod
    def clean_sentence(sentence):
        """

        This method removes all special characters, special characters and ticks

        Args:
            @param: sentence:  A sentence to be cleaned

        Returns:
            A new sentence in a normalized way

    """
        sentence = sentence.lower()
        sentence = ''.join((c for c in unicodedata.normalize('NFD', sentence) if unicodedata.category(c) != 'Mn'))
        sentence = (re.sub(r"[^a-zA-Z0-9]+", ' ', sentence))
        return sentence

    def extract_information(self, sentence, threshold=0.0, name=None, k=1, model_type=ModelType.intent):
        """
        This method extracts information depending of the model type
        Args:
            @param: sentence:  A sentence where information will be extracted

            @param: name:  The name of the entity type.

            @param: k:  Number of results to be found

            @param: model_type:  If model is for intents or entities

        Returns:
            A dict containing information found in sentence
        """
        results = self.model.predict(self.clean_sentence(sentence), k=k, threshold=threshold)
        final = []
        for label, prob in zip(results[0], results[1]):
            if name is not None:
                final.append(
                    {"prediction": label.replace("__label__", "http://127.0.0.1/ockb/resources/"), "label": label,
                     "probability": prob, "entity": name})
            else:
                final.append(
                    {"prediction": label.replace("__label__", "http://127.0.0.1/ockb/resources/"), "label": label,
                     "probability": prob})
        if model_type == ModelType.intent:
            return {"intent": final}
        elif model_type == ModelType.entities:
            return {"entities": final}

def get_generic_entities(sentence):
    result = []
    doc = nlp(sentence)
    entities = doc.ents
    for ent in entities:
        # print(ent.text, ent.label_)
        result.append({"label": ent.text, "entity": ent.label_})
    return result

class AgentNotFoundException(Exception):
    def __init__(self):
        Exception.__init__(self, "Must provide a valid agent name")

class ModelNotFoundException(Exception):
    def __init__(self):
        Exception.__init__(self, "No models found related to agent")


import streamlit as st
import plotly.express as px
from prophet import Prophet
from prophet.plot import plot_plotly, plot_components_plotly
import plotly.graph_objects as go
import pandas as pd
from StreamlitHelper import Toc, get_img_with_href, read_df, create_table
import numpy as np

st.set_page_config(
    page_title="Art Index",
    page_icon="data/Vertical-BLACK2.ico",
)
# inject CSS to hide row indexes and style fullscreen button
inject_style_css = """

            """
st.markdown(inject_style_css, unsafe_allow_html=True)

def create_paragraph(text):
    st.markdown('' + text + '', unsafe_allow_html=True)

df = read_df('data/auctions_clean.csv')
# Fix data
df = df[df["date"] >= 2001]
df = df[df["date"] <= 2021]
df["date"] = df["date"].astype("int")
df = df.sort_values(by=["date"])
df.loc[df["technique"]=="Mixed tech", "technique"] = "Mixed technique"
df_hist = read_df('data/historical_avg_price.csv')
df_hist = df_hist[df_hist["date"] >= 2001]
df_hist = df_hist.groupby("date").sum()

#temp fix
df.loc[df["technique"] == "Silk print", "category"] = "Graphics"
df.loc[df["technique"] == "Vitrography", "category"] = "Graphics"
df.loc[df["technique"] == "Wood cut", "category"] = "Graphics"

# Sidebar Table of Contents
toc = Toc()
toc.placeholder(sidebar=True)

kanvas_logo = get_img_with_href('data/horisontal-BLACK.png', 'https://kanvas.ai', '200px')
st.sidebar.markdown(kanvas_logo, unsafe_allow_html=True)

kanvas_logo = get_img_with_href('data/horisontal-BLACK.png', 'https://kanvas.ai', '400px')
st.markdown(kanvas_logo, unsafe_allow_html=True)

# TITLE
st.title('Eesti kunstiindeks')
toc.header('Ülevaade')
create_paragraph('''Kanvas.ai Art Index on vahend kunstiinvestoritele.

Kanvas.ai kunstiindeks on andmebaas, mis on loodud Eesti kunstioksjonite \n viimase 20 aasta (2001-2021) müügiajaloo põhjal, eesmärgiga muuta kunst ja kunsti investeerimine \n kõigile huvilistele arusaadavamaks.

Andmed on kogutud Eesti peamiste galeriide avalike oksjonite tulemuste põhjal, mis annab ülevaate sellest, kuidas kunstiturg \nkäib ajas ning millised kunstimeediumid ja autorid on kõige paremini investeerinud.

Andmete põhjal on selge, kuidas kunsti populaarsus on viimastel aastatel teinud hiigelsuure hüppe nii hindade kui ka mahu poolest. Näiteks paljude kunstiteoste liikide puhul on hinnatõus või tootlus olnud üle 10% aastas. Seega on \n hästi valitud kunstiteos hea valik, et kaitsta oma raha inflatsiooni eest.

Kanvas.ai kunstiindeks ei sisalda praegu teavet oksjonivälise kunsti kohta, kuid \n plaanime hakata koguma andmeid ka NFTKanvas.ai \n lehel müüdud NFT-kunstimeedia kohta.

Praegu on kunstiindeksi metoodika väljatöötamisel. Palun saatke meile e-posti aadressil info@kanvas.ai kõik ettepanekud ja kommentaarid.''')

# FIGURE - date and average price
toc.subheader('Joonis - ajalooline hinnakäitumine')
fig = px.area(df_hist, x=df_hist.index, y="avg_price",
              labels={
                 "avg_price": "Indeksi ajalooline tootlus (€)",
                 "date": "Enampakkumise aasta",
             })
fig.update_layout(margin=dict(l=5, r=5, t=5, b=5))
st.plotly_chart(fig, use_container_width=True)
create_paragraph('''Kunstiindeks annab ülevaate kunsti hinna tõusust ja langusest. Kunsti hind on viimastel aastatel teinud märgatava hüppe. Huvi kunstioksjonite turul kunsti investeerimise vastu on pärast pandeemiat hüppeliselt kasvanud.''')

# TABLE - categories average price
toc.subheader('Tabel - ajalooline hinnakäitumine tehnika kaupa')
table_data = create_table(df, "category", df["category"].unique(), calculate_volume=False, table_height=150)
st.table(table_data)
create_paragraph('''Järjestatud meediumi ehk tehnika järgi, vastavalt sellele, milline meedium domineerib enim müüdud teostes.''')

# Art Index Performance Prediction
toc.subheader('Kunstiindeksi tulemuslikkuse prognoosimine')
df_art = pd.read_csv('./data/historical_avg_price.csv')
df_art[['ds', 'y']] = df_art[['date', 'avg_price']]
df_art = df_art[['ds', 'y']]
m = Prophet()
m.fit(df_art)
future = m.make_future_dataframe(periods = 20428)
forecast = m.predict(future.tail(1770))
m.plot(forecast)
fig1 = plot_plotly(m, forecast)
st.plotly_chart(fig1)
fig = go.Figure()
fig.add_trace(go.Scatter(x=forecast['ds'], y=forecast['yhat'], mode='lines', name='Forecast'))
st.plotly_chart(fig, use_container_width=True)

create_paragraph('''Selle analüüsi kohaselt prognoositakse, et kunstiindeksi hind tõuseb märkimisväärselt, tõustes 4 671,681 eurolt 2021. aasta veebruaris 5 469,599 eurole 2025. aasta detsembriks.
''')
# FIGURE - date and volume
toc.subheader('Joonis - ajalooline mahu kasv')
fig = px.area(df_hist, x=df_hist.index, y="volume",
             labels={
                 "volume": "Maht (€)",
                 "date": "Oksjoni aasta",
             })
fig.update_layout(margin=dict(l=5, r=5, t=5, b=5))
st.plotly_chart(fig, use_container_width=True)
create_paragraph('''Mahu kasv annab meile ülevaate sellest, kui palju on oksjonite käive aja jooksul tõusnud ja langenud.

Näiteks 2001. aastal oli oksjonikäive umbes 174 000 eurot, siis 2021. aastal oli oksjonikäive 4,5 miljonit eurot. Kindlasti mängib väga olulist rolli krooni asendamine euroga, samuti on lisandunud rohkem oksjonigaleriisid. Siiski on kunstimüük alates 2019. aastast teinud märkimisväärse hüppe, mis on suurim 20 aasta jooksul. Viimane suur muutus toimus 2006-2009 majanduskriisi mõjude tõttu.''')

# TABLE - categories volume
toc.subheader('Tabel - ajalooline mahu kasv tehnika järgi')
table_data = create_table(df, "category", df["category"].unique(), calculate_volume=True, table_height=150)
st.table(table_data)
create_paragraph('''Sellest tabelist näeme, millisel meediumil on olnud suurim käive. Antud andmete põhjal näeme näiteks, et graafika on kõige populaarsem ja suurima aastase käibe kasvuprotsendiga (204% aastas 20 aasta jooksul ja 35% õlimaal samal ajal).''')

# FIGURE - treemap covering categories, techniques and authors by volume and overbid
toc.subheader('Joonis - Kunstimüük tehnika ja kunstniku järgi (alg- ja lõpphinna erinevus)')

df['start_price'] = df['start_price'].fillna(df['end_price'])
df['overbid_%'] = (df['end_price'] - df['start_price'])/df['start_price'] * 100
df['art_work_age'] = df['date'] - df['year']
df2 = df.groupby(['author', 'technique', 'category']).agg({'end_price':['sum'], 'overbid_%':['mean']})
df2.columns = ['total_sales', 'overbid_%']
df2 = df2.reset_index()

df2.loc[df2["category"] == "Mixed medium", "technique"] = df2["author"]
df2.loc[df2["category"] == "Mixed medium", "author"] = None
df2.loc[df2["category"] == "Drawing", "technique"] = df2["author"]
df2.loc[df2["category"] == "Drawing", "author"] = None

artists = df2["author"].unique()
artists = [artist for artist in artists if artist is not None]
artists = np.concatenate([["Kõik kunstnikud"], artists])
selected_artist =st.selectbox('Valige kunstnik', options=artists, key="1")
if selected_artist=='Kõik kunstnikud':

    fig = px.treemap(df2, path=[px.Constant("Techniques"), 'category', 'technique', 'author'], values='total_sales',
                      color='overbid_%',
                      color_continuous_scale='RdBu',
                      range_color = (0, df['overbid_%'].mean() + df['overbid_%'].std() / 2),
                      labels={
                         "overbid_%": "Overbid (%)",
                         "total_sales": "Total Sales",
                         "author": "Author",
                      })
else:
    artist_df = df2[df2["author"] == selected_artist]
    fig = px.treemap(artist_df, path=["author", "category", "technique"], values="total_sales",
                    color="overbid_%", color_continuous_scale="RdBu",
                    range_color=(-20, 100), labels={
                        "yearly_performance": "Historical Performance (%)",
                        "total_sales": "Total Sales",
                        "author": "Author",
                    })

fig.update_layout(margin=dict(l=5, r=5, t=5, b=5))
fig.update_traces(hovertemplate='%{label}
 Total Sales: %{value}
 Overbid (%): %{color:.2f}',)
st.plotly_chart(fig, use_container_width=True)

if selected_artist!='Kõik kunstnikud':
    artist_df = df2[df2["author"] == selected_artist]
    columns = ["author", "category", "technique", "total_sales", "overbid_%"]
    data = artist_df[columns]

    data = data.rename(columns={
        "author":"Kunstnik",
        "category":"Kategooria",
        "technique":"Tehnika",
        "total_sales": "Müük kokku",
        "overbid_%": "Ülepakkumise %",
    })
    data = data.reset_index(drop=True)
    st.write(data)

create_paragraph('''Tehnikad ja kunstnikud, kus värviskaala annab meile ülevaate, kui palju kunsti on oksjonite ajal ülepakkumisi tehtud ning mahud on järjestatud tehnika ja kunstniku järgi.

Näiteks sinine värv näitab kunstnikke ja meediume, mille puhul oli ülepakkumiste protsent kõige suurem. Maht on näidatud ka kunstniku nime kõrval. Näiteks Konrad Mägi on kõige rohkem müüdud kunstiteoseid, kuid see tabel näitab, et kõige suurem ülepakkumine läheb Olev Subbi töödele, mis puudutab tempera meediumit. (711,69 % hinnatõus alghinnast, samas kui Konrad Mägi puhul on numbrid 59,06 % õli kartongil ja 85,44 % õli lõuendil meediumi puhul). Kuigi mahu poolest on Konrad Mägi endiselt Subbi ees.''')

# FIGURE - treemap covering categories, techniques and authors by volume and overbid
toc.subheader('Joonis - Kunstimüük tehnika ja kunstniku järgi (ajalooline hinnakäitumine)')
table_data = create_table(df, "author", list(df["author"].unique()), calculate_volume=False, table_height=250)
df["yearly_performance"] = [table_data[table_data["Author"] == x]["Yearly growth (%)"] for x in df["author"]]
df2 = df.groupby(['author', 'technique', 'category']).agg({'end_price':['sum'], 'yearly_performance':['mean']})
df2.columns = ['total_sales', 'yearly_performance']
df2 = df2.reset_index()

df2.loc[df2["category"] == "Mixed medium", "technique"] = df2["author"]
df2.loc[df2["category"] == "Mixed medium", "author"] = None

df2.loc[df2["category"] == "Drawing", "technique"] = df2["author"]
df2.loc[df2["category"] == "Drawing", "author"] = None

artists = df2["author"].unique()
artists = [artist for artist in artists if artist is not None]
artists = np.concatenate([["Kõik kunstnikud"], artists])

selected_artist2 =st.selectbox('Valige kunstnik', options=artists, key="2")
if selected_artist2=='Kõik kunstnikud':

    fig = px.treemap(df2, path=[px.Constant("Techniques"), 'category', 'technique', 'author'], values='total_sales',
                      color='yearly_performance',
                      color_continuous_scale='RdBu',
                      range_color = (-20, 100),
                      labels={
                         "yearly_performance": "Historical Performance (%)",
                         "total_sales": "Total Sales",
                         "author": "Author",
                      })
else:
    artist_df = df2[df2["author"] == selected_artist2]

    fig = px.treemap(artist_df, path=[px.Constant("Techniques"), 'category', 'technique', 'author'], values='total_sales',
                        color='yearly_performance',
                        color_continuous_scale='RdBu',
                        range_color = (-20, 100),
                        labels={
                            "yearly_performance": "Historical Performance (%)",
                            "total_sales": "Total Sales",
                            "author": "Author",
                        })

fig.update_layout(margin=dict(l=5, r=5, t=5, b=5))
fig.update_traces(hovertemplate='%{label}
 Total sales: %{value}
 Annual return (%): %{color:.2f}',)
st.plotly_chart(fig, use_container_width=True)

if selected_artist2!='Kõik kunstnikud':

    artist_df = df2[df2["author"] == selected_artist2]
    columns = ["category", "technique", "author", "total_sales", "yearly_performance"]
    data = artist_df[columns]

    data = data.rename(columns={
        "author":"Kunstnik",
        "category":"Kategooria",
        "technique":"Tehnika",
        "total_sales": "Müük kokku",
        "yearly_performance": "Ajaloolised tulemused (%)",
    })
    data = data.reset_index(drop=True)
    st.write(data)

create_paragraph('''
Tehnikad ja kunstnikud, kus värviskaala annab meile ülevaate ajaloolistest hinnatulemustest ja mahust tehnika ja kunstniku järgi järjestatuna.

Näiteks sinine värv näitab kunstnikke ja meediume, mille ajalooline hinnakasv oli kõige suurem. Kunstniku nime kõrval on näidatud ka maht. Näiteks Konrad Mägi on kõige rohkem müüdud kunstiteoseid, kuid see tabel näitab, et kõrgeim keskmine ajalooline hind läheb Karin Lutsu töödele (498,84 % keskmine hinnakasv aastate jooksul, samas kui Konrad Mägi puhul on see arv 198,95 %). Kuigi Konrad Mägi on mahu poolest Lutsist ikka veel üle.''')

# TABLE - best authors average price
author_sum = df.groupby(["author"], sort=False)["end_price"].sum()
top_authors = author_sum.sort_values(ascending=False)[:10]

toc.subheader('Tabel - Top 10 parima tulemusega kunstnikud (hinnakäitumine)')
table_data = create_table(df, "author", top_authors.index, calculate_volume=False, table_height=250)
st.table(table_data)
create_paragraph('''Selles tabelis on esitatud kõige populaarsemad kunstnikud ja nende ajalooline hinnakasvuprotsent. Protsent on arvutatud aasta keskmiste lõpphindade erinevuste põhjal.

Tabeli liider on Konrad Mägi, kelle kasvuprotsent on keskmiselt 198,95%. Seda kasvuprotsenti mõjutab kindlasti tema teoste ainulaadsus. Konrad Mägil on oksjonitel välja pandud piiratud arv teoseid. Teisel kohal on Eduard Wiiralt, kelle teoseid on erinevalt Konrad Mägist palju oksjonitel eksponeeritud. Wiiralti tööde alghinnad on madalad ja ta on kollektsionääride seas väga populaarne.''')

# TABLE - best authors volume
toc.subheader('Tabel - 10 kõige edukamat artisti (mahu kasv)')
table_data = create_table(df, "author", top_authors.index, calculate_volume=True, table_height=250)
st.table(table_data)
create_paragraph('''Selles tabelis on esitatud kunstiteoste käive ja keskmine aastane kasv. Siin on Wiiralt 8. kohal ja Konrad Mägi 1. kohal. Kuna kasvuprotsent on kogu perioodi (2001-2021) käibe kohta, siis asuvad tabeli tipus kunstnikud, kelle teoseid on kõige rohkem ostetud.
''')

# FIGURE - date and price
toc.subheader('Joonis - Kunstiteose vanus vs. hind')
df['art_work_age'] = df['date'] - df['year']
q_low = df["end_price"].quantile(0.1)
q_hi  = df["end_price"].quantile(0.9)
df = df[(df["end_price"] < q_hi) & (df["end_price"] > q_low)]
fig = px.scatter(df.dropna(subset=["decade"]), x="art_work_age", y="end_price", color="category",
                 animation_frame="date", animation_group="technique", hover_name="technique",
                 size='date', hover_data=['author'], size_max=15, range_x=[-4,130], range_y=[-1000,8200],
                 labels={
                     "end_price": "Oksjoni lõplik müügihind (€)",
                     "art_work_age": "Kunstitöö vanus",
                     "author": "Autor",
                     "category": "Tehnika",
                     "decade": "Aastakümnend"
                  })
fig.update_layout(margin=dict(l=5, r=5, t=5, b=5))
st.plotly_chart(fig, use_container_width=True)
create_paragraph('''Antud graafiku põhjal on võimalik määrata teose hinda vastavalt kunstiteose vanusele ja tehnikale. Tehnikad on eristatud värvide kaupa.

Vanim töö pärineb aastast 1900, kuid ei ole kõige kallim. Üldiselt on näha, et vanemad tööd on kallimad, välja arvatud Olev Subbi. On näha, et Teise maailmasõja eelsed tööd aastatest 1910-1940 on müüdud kallimalt.''')

# FIGURE - size and price
toc.subheader('Joonis - Kunstiteose suurus vs. hind')
df["dimension"] = df["dimension"] / (100*100)
q_low = df["dimension"].quantile(0.1)
q_hi  = df["dimension"].quantile(0.9)
df = df[(df["dimension"] < q_hi) & (df["dimension"] > q_low)]
fig = px.scatter(df.dropna(subset=["dimension"]), x="dimension", y="end_price", color="category",
                 animation_frame="date", animation_group="technique", hover_name="technique",
                 size='date', hover_data=['author'], size_max=15, range_x=[-0.03, 4], range_y=[-1000,8200],
                 labels={
                     "end_price": "Oksjoni lõplik müügihind (€)",
                     "dimension": "Mõõtmed (m²)",
                     "author": "Autor",
                     "category": "Tehnika",
                  })
fig.update_layout(margin=dict(l=5, r=5, t=5, b=5))
st.plotly_chart(fig, use_container_width=True)
create_paragraph('''Ülevaade töö mõõtmete, tehnika ja hinna vahelisest suhtest. Paljud väiksema formaadiga tööd on sageli kallimad kui suured. Teose suurus ei tähenda tingimata, et see on kallim. Pigem on olulisem autor ja kui teose suurus. Näiteks Konrad Mägi Õlimaa on mõõtkavas keskmiste hulgas, kuid hinnaskaalal teistest tunduvalt kõrgemal (127 823 eurot haamrihind), samas kui suurima teose (Toomas Vint) haamrihind on 7094 eurot.''')

def create_credits(text):
    st.markdown('' + text + '', unsafe_allow_html=True)
create_credits('''Autoriõigus: Kanvas.ai''')
create_credits('''Autorid: Astrid Laupmaa, Julian Kaljuvee, Markus Sulg''')
create_credits('''Allikas: Estonian public art auction sales (2001-2021)''')
create_credits('''Other credits: Inspired by the original Estonian Art Index created by Riivo Anton;
Generous support from Tezos Foundation''')

toc.generate()

@st.cache()
def convert_df():
    # IMPORTANT: Cache the conversion to prevent computation on every rerun
    return read_df('data/auctions_clean.csv').to_csv().encode('utf-8')

csv = convert_df()
st.download_button(label="Andmete allalaadimine",data=csv, file_name='estonian_art_index.csv', mime='text/csv')


import translators.server as ts
from num2words import num2words
from datetime import datetime
import pytz

class DateTimeQuery:
    def __init__(self, config):
        self.config = config

    def get_time(self, ner):
        place_name = ""
        for entity in ner:
            if entity["entity"] == "B-place_name":
                place_name += entity["word"]

        if place_name == "":
            place_name = self.config.get_config("default_city")
        try:
            timezone = pytz.timezone(
                ts.google(place_name, from_language="ru", to_language="en")
            )
        except:
            timezone = pytz.timezone("Europe/Moscow")
        time = datetime.now(timezone)
        hour = self.convert_temp(time.hour)
        minute = self.convert_temp(time.minute)
        return f"Сейчас в {place_name} {hour} часов {minute} минут"

    def convert_temp(self, number):
        return num2words(number, to="cardinal", lang="ru")


import requests
from bs4 import BeautifulSoup
from daum_news_fnc import get_news_title_and_content
page = 3 # 수집 할 페이지 수
cnt = 0 # 수집 기사수를 저장하는 변수
for page_num in range(1, page + 1):
    print(f"{page_num} page " + "■"* 100)
    url = f"https://news.daum.net/breakingnews/digital?page={page_num}"

    # 다음 뉴스 웹사이트 페이지(15건)를 돌면서, 기사 수집
    result = requests.get(url)
    soup = BeautifulSoup(result.text, "html.parser")
    title_list = soup.select("ul.list_news2 a.link_txt")
    for i, tag in enumerate(title_list):
        new_url = tag["href"]
        title, content = get_news_title_and_content(new_url)
        cnt += 1
        print("=" * 100)
        print(f"URL: {new_url}")
        print(f"{cnt}. 뉴스제목: {title}")
        print("=" * 100)
        print(f"{cnt}. 뉴스 본문: {content}")


from flask import Flask, request, make_response
from currencyExchange import *
import argparse
import os
import json

app = Flask(__name__)

##
# Confirms the service is working on a browser
# @return {dict} a symbolic confirmation of the service
##
@app.route("/", methods=["GET"])
def retornodummy():
    r = make_response("Currency Exchange Service Works")
    return r

##
# Provides the user with the exchange rate of two currencies
# @param  {dict}   contenido de la peticion a la funcion
        # {
        #     "baseCurrency":EUR,
        #     "baseCurrencyAmount":$$$,
        #     "quoteCurrency":GBP
        # }
# @return {dict}   a symbolic confirmation of the connection
        #{
        #      "exchangeRate":$$$
        #      "feeCost":$$$
        #      "quoteAmountBalance":$$$
        #}
##
@app.route("/getexchangerate", methods=["POST", "GET"])
def getexchangerate():
    req = request.get_json(silent=True, force=True)

    #we get the parameters we need from the request
    baseCurrency = req.get("baseCurrency")
    baseCurrencyAmount = req.get("baseCurrencyAmount")
    quoteCurrency = req.get("quoteCurrency")

    #we process the BUSINESS LOGIC to get the values requested by the user
    exchangeRate = getRate(baseCurrency, quoteCurrency,baseCurrencyAmount)
    feeCost = getFeeCost(baseCurrency,baseCurrencyAmount)
    quoteAmountBalance = getQuoteAmountBalance(quoteCurrency)

    res = {"exchangeRate":exchangeRate, "feeCost":feeCost, "quoteAmountBalance":quoteAmountBalance}

    # Construccion de respuesta en formato json
    # ********************************************
    res = json.dumps(res, indent=4)

    r = make_response(res)

    r.headers["Content-Type"] = "application/json"
    # ********************************************
    return r

##
# Makes a transaction between two currencies
# @param  {dict}   contenido de la peticion a la funcion
        # {
        #     "baseCurrency":EUR,
        #     "quoteCurrency":GBP
        #     "quoteCurrencyAmount": $$$
        # }
# @return {dict}   a symbolic confirmation of the connection
        #{
        #      "baseCurrencyBalance":$$$
        #      "quoteCurrencyBalance":$$$
        #}
##
@app.route("/exchangecurrency", methods=["POST"])
def exchangecurrency():
    req = request.get_json(silent=True, force=True)

    #we get the parameters we need from the request
    baseCurrency = req.get("baseCurrency")
    quoteCurrency = req.get("quoteCurrency")
    quoteCurrencyAmount = req.get("quoteCurrencyAmount")

    #we process the BUSINESS LOGIC to get the values requested by the user
    tradeDataSet = exchange(baseCurrency, quoteCurrency, quoteCurrencyAmount)

    res = {"exchangeRate":tradeDataSet["exchangeRate"], "feeCost":tradeDataSet["feeCost"], "quoteAmountBalance":tradeDataSet["quoteAmountBalance"]}

    # Construccion de respuesta en formato json
    # ********************************************
    res = json.dumps(res, indent=4)

    r = make_response(res)

    r.headers["Content-Type"] = "application/json"
    # ********************************************
    return r

##
# Provides the current balance statuses
# @return {dict}  the dict of the current balances
        #{"USD": 1000,
        #"GBP": 1000,
        #"EUR": 1000,
        #"JPY": 1000,
        # ...
        #}
##
@app.route("/getallquotesbalance", methods=["GET"])
def getallquotesbalance():
    res = getAllQuotesBalance()

    # Construccion de respuesta en formato json
    # ********************************************
    res = json.dumps(res, indent=4)

    r = make_response(res)

    r.headers["Content-Type"] = "application/json"
    # ********************************************
    return r

##
# Provides the user with the total amount of fees charged so far in USD
# @return {dict} a set with the amount charged
        #{"USD": 1000}
##
@app.route("/calculatefees", methods=["GET"])
def calculateFees():
    res = {"USD":calculateTotalFees()}

    # Construccion de respuesta en formato json
    # ********************************************
    res = json.dumps(res, indent=4)

    r = make_response(res)

    r.headers["Content-Type"] = "application/json"
    # ********************************************
    return r

##############################################################################################################################################
#MAIN PROCESS TO RUN THE FLASK SERVICE
if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='Currency Exchange Service')
    parser.add_argument('--port', dest='noport', metavar='NNNN', type=int, help='The port number for webservice listener')
    parser.add_argument('--debug', dest='debug', metavar='N', type=int, help='debug mode, 1 for turn on')
    args = parser.parse_args()
    # asignacion de puerto del webhook y modo debug
    # si el puerto no es asignado, se toma 7700 por default
    debug = bool(args.debug)
    # --------------------------------------------------------------------
    if args.noport is None:
        noport = 7700
    else:
        noport = args.noport

    port = int(os.getenv("PORT", noport))
    print("Starting app on port %d" %port)
    app.run(debug=debug, port=port, host="0.0.0.0")


from keras.models import Model
from YOLO_V3 import decode_netout, correct_yolo_boxes, do_nms, draw_boxes
import numpy as np
from numpy import expand_dims
from keras.models import load_model
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
import cv2
from PIL import Image
from Screen_cap import grab_screen
from GetKeyPressed import key_check
import time

#from matplotlib import pyplot
#from matplotlib.patches import Rectangle

anchors = [[116,90,  156,198,  373,326],  [30,61, 62,45,  59,119], [10,13,  16,30,  33,23]]
labels = ["person", "bicycle", "car", "motorbike", "aeroplane", "bus", "train", "truck", \
          "boat", "traffic light", "fire hydrant", "stop sign", "parking meter", "bench", \
          "bird", "cat", "dog", "horse", "sheep", "cow", "elephant", "bear", "zebra", "giraffe", \
          "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee", "skis", "snowboard", \
          "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard", \
          "tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", \
          "apple", "sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", \
          "chair", "sofa", "pottedplant", "bed", "diningtable", "toilet", "tvmonitor", "laptop", "mouse", \
          "remote", "keyboard", "cell phone", "microwave", "oven", "toaster", "sink", "refrigerator", \
          "book", "clock", "vase", "scissors", "teddy bear", "hair drier", "toothbrush"]

model = load_model('D:/Projects/self_driving_car/Save_model/model.h5')

filename = 'C:/Users/yasht/Desktop/junk/Holi/DSC_0158.JPG'

def load_image_pixels(filename, shape):
    image = load_img(filename)
    width, height = image.size
    image = load_img(filename, target_size=shape)
    image = img_to_array(image)
    image = image.astype('float32')
    image /= 255.0
    image = expand_dims(image, 0)
    return image, width, height

def nparray_to_image(img):

    data = img.ctypes.data_as(POINTER(c_ubyte))
    image = ndarray_image(data, img.ctypes.shape, img.ctypes.strides)

    return image

input_w, input_h = 416, 416

#image, image_w, image_h = load_image_pixels(filename, (input_w, input_h))

#print(type(image))
#print(image.shape)

#yhat = model.predict(image)

#print([a.shape for a in yhat])

class_threshold = 0.6
nms_threshold = 0.5

#boxes = list()
#for i in range(len(yhat)):
#	boxes += decode_netout(yhat[i][0], anchors[i], class_threshold,nms_threshold, input_h, input_w)

#correct_yolo_boxes(boxes, image_h, image_w, input_h, input_w)

#do_nms(boxes, 0.5)

#org_image = cv2.imread(filename,0)

#print(type(org_image))

#draw_boxes(org_image, boxes, labels, class_threshold)

#org_image = (org_image.squeeze()*255).astype(np.uint8)

#img = Image.fromarray(org_image, mode='RGB')
#img.show()

#image = Image.fromarray(image.astype('uint8'), 'RGB')

#image = nparray_to_image(image)

#cv2.imwrite(filename[:-4] + '_detected' + filename[-4:], org_image)
image_w, image_h = 1250, 720

def main():
    paused = False
    while True:
        if not paused:
            screen = grab_screen(region=(0,30,1250,750))
            screen = cv2.cvtColor(screen, cv2.COLOR_BGR2RGB)
            org_image = screen
            screen = cv2.resize(screen,(input_w, input_h))
            screen = img_to_array(screen)
            screen /= 255.0
            screen = expand_dims(screen, 0)
            #screen = cv2.resize(screen,(1, 416, 416, 3))
            yhat = model.predict(screen)
            boxes = list()
            for i in range(len(yhat)):
            	boxes += decode_netout(yhat[i][0], anchors[i], class_threshold,nms_threshold, input_h, input_w)
            correct_yolo_boxes(boxes, image_h, image_w, input_h, input_w)
            do_nms(boxes, 0.5)
            draw_boxes(org_image, boxes, labels, class_threshold)
            cv2.imshow("fens", org_image)
            #cv2.imshow("crop", crop)

            #keys = key_check()

            #output = keys_to_output(keys)
            #training_data.append([screen/255,output])
            #last_time = time.time()

            #if len(training_data) % 250 == 0:
            #    print(len(training_data))

            #    if len(training_data) == 2500:
            #        np.save(file_name,training_data)
            #        print('SAVED')
            #        training_data = []
            #        starting_value += 1
            #        file_name = 'D:/Projects/self_driving_car/Training_data/training_data_final-{}.npy'.format(starting_value)

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

        keys = key_check()
        if 'T' in keys:
            if paused:
                paused = False
                print('unpaused!')
                time.sleep(1)
            else:
                print('Pausing!')
                paused = True
                time.sleep(1)

main()


from typing import Any, Callable
from core.messagebus.messagebus import Admin, Consumer, Publisher
from core.rpc.rpc import Caller, Message, Result
import logging
from ulid import ULID
import asyncio

class MessagebusCaller(Caller):

    def __init__(
        self,
        logger: logging.Logger,
        admin: Admin,
        publisher: Publisher,
        consumer_factory: Callable[[], Consumer],
        timeout: float = 30,
        check_reply_interval: float = 0.1
    ):
        self.logger = logger
        self.admin = admin
        self.publisher = publisher
        self.consumer_factory = consumer_factory
        self.timeout = timeout
        self.check_reply_interval = check_reply_interval

    async def call(self, rpc_name: str, *args: Any, **kwargs: Any):
        random_uuid = str(ULID())
        reply_event_name = f'reply_{rpc_name}_{random_uuid}'
        await self.admin.create_events([reply_event_name])
        reply_consumer = self.consumer_factory()
        reply_received_event = asyncio.Event()
        call_result, call_error = None, None

        @reply_consumer.register(reply_event_name)
        async def consume_reply(result_dict: Any):
            nonlocal call_result, call_error
            result = Result.from_dict(result_dict)
            call_result, call_error = result.result, result.error
            reply_received_event.set()
            await reply_consumer.stop()

        try:
            task = asyncio.create_task(reply_consumer.start())
            await self.publisher.publish(
                rpc_name,
                Message(
                    reply_event=reply_event_name, args=args, kwargs=kwargs
                ).to_dict()
            )
            await asyncio.gather(task)
            await asyncio.wait_for(
                reply_received_event.wait(), timeout=self.timeout
            )
        except asyncio.TimeoutError:
            self.logger.error(
                '�� [messagebus-rpc-caller] ' +
                f'Timeout while waiting for reply event {reply_event_name}'
            )
            raise Exception(
                f'Timeout while waiting for reply event: {reply_event_name}'
            )
        finally:
            await self._clean_up(reply_consumer, reply_event_name)
        # raise call_error or return call_result
        if call_error != '':
            self.logger.error(
                '�� [messagebus-rpc-caller] RPC ' +
                f'"{rpc_name}" returning error: {call_error}'
            )
            raise Exception(call_error)
        self.logger.info(
            '�� [messagebus-rpc-caller] RPC ' +
            f'"{rpc_name}" returning result: {call_result}'
        )
        return call_result

    async def _clean_up(self, reply_consumer: Consumer, reply_event_name: str):
        try:
            await reply_consumer.stop()
        except (asyncio.CancelledError, GeneratorExit, Exception):
            self.logger.error('�� [messagebus-rpc-caller]', exc_info=True)
        try:
            await self.admin.delete_events([reply_event_name])
        except (asyncio.CancelledError, GeneratorExit, Exception):
            self.logger.error('�� [messagebus-rpc-caller]', exc_info=True)


## import modules here
import helper
from sklearn import tree, model_selection
import pandas as pd
import pickle
from sklearn.metrics import f1_score
import nltk
from nltk.tokenize import word_tokenize
################# training #################
##nltk.download('averaged_perceptron_tagger')
##def total_prefix(word):
##    suffixes=('THELESS', 'TATIVES', 'MINATE', 'UNDERREPORT', 'COMEDIENNE', 'DULATE', 'JAHIDEEN', 'NERATE', 'NASIONAL', 'SCRIBE', 'ACKED', 'ANCED', 'MINES',
##          'NEERS', 'NOSED', 'POSED', 'SENTS', 'TANDS', 'TIANE', 'UILLE', 'VERSE', 'ADOR', 'ELLE', 'ENDS', 'ETTE', 'EURS', 'EVAN', 'IBED', 'LIED', 'MAIN', 'NECT', 'NEER', 'NOSE',
##          'PATH', 'PPLY', 'TECT', 'TUNE', 'WEES', 'DAD', 'ERU', 'ETE', 'EUR', 'JAN', 'LET', 'MAR', 'TIF', 'TIK', 'YOR')
##
##    prefixes=('COUNTER', 'INTER', 'NITRO', 'UNDER', 'AERO', 'DEMO', 'IDIO', 'OVER', 'SOCI', 'TELE', 'BIO', 'COM', 'LAV', 'LEG', 'MIS', 'NAI', 'NAT')
##
##
##    spell = word[:word.index(":")]
##    spell = spell.lower()
##    pref = 0
##    sufx = 0
##    for pre in range(0,len(prefixes)):
##        if spell.startswith(prefixes[pre]):
##            pref = pre+1
##    for suf in range(0,len(suffixes)):
##        if spell.endswith(suffixes[suf]):
##            sufx = suf+1
##
##    return pref,sufx

##def first_vowel(pronounce):
##    vowel = ["AA","AE","AH","AO","AW","AY","EH","ER","EY","IH","IY","OW","OY","UH","UW"]
##    first = 0
##    for pro in pronounce:
##        if pro[:2] in vowel:
##            first = vowel.index(pro[:2])+1
##            break
##    return first
##def second_vowel(pronounce):
##    vowel = ["AA","AE","AH","AO","AW","AY","EH","ER","EY","IH","IY","OW","OY","UH","UW"]
##    second = 0
##    time = 0
##    for pro in pronounce:
##        if pro[:2] in vowel:
##            if time == 0:
##                time = time+1
##                continue
##            if time == 1:
##                time = time+1
##                second = vowel.index(pro[:2])+1
##                break
##            else:
##                break
##    return second
##def third_vowel(pronounce):
##    vowel = ["AA","AE","AH","AO","AW","AY","EH","ER","EY","IH","IY","OW","OY","UH","UW"]
##    third = 0
##    time = 0
##    for pro in pronounce:
##        if pro[:2] in vowel:
##            if time < 2:
##                time = time+1
##                continue
##            if time == 2:
##                time = time+1
##                third = vowel.index(pro[:2])+1
##                break
##            else:
##                break
##    return third
##def forth_vowel(pronounce):
##    vowel = ["AA","AE","AH","AO","AW","AY","EH","ER","EY","IH","IY","OW","OY","UH","UW"]
##    forth = 0
##    time = 0
##    for pro in pronounce:
##        if pro[:2] in vowel:
##            if time < 3:
##                time = time+1
##                continue
##            if time == 3:
##                time = time+1
##                forth = vowel.index(pro[:2])+1
##                break
##            else:
##                break
##    return forth

def vowel_num(pronounce):
    vowel = ["AA","AE","AH","AO","AW","AY","EH","ER","EY","IH","IY","OW","OY","UH","UW"]
    vowel_num = 0
    word_vowel = []
    for tiny_pro in pronounce:
        if tiny_pro[:2] in vowel:
            vowel_num = vowel_num+1
            word_vowel.append(tiny_pro)

    return vowel_num,word_vowel
def combine(pronounce):
    vowel = ["AA","AE","AH","AO","AW","AY","EH","ER","EY","IH","IY","OW","OY","UH","UW"]
    com = ""
    comp = []
    for tiny in pronounce:
        if tiny[:2] in vowel:
            comp.append(vowel.index(tiny[:2])+1)

    comp.reverse()
    la = 0
    for vo in comp:
        la = la*100+vo
##    la = ((english_letter.index(spell[-3])+1)*100 +(english_letter.index(spell[-2])+1))*100+english_letter.index(spell[-1])+1
##    for aa in comp:
##        if aa >9:
##            com = com+str(aa)
##        else:
##            aa = "0"+str(aa)
##            com = com+aa

    return la
##def typeword(word):
##
##    total_type = ['RB','JJ','FW','NNP','JJR','CC','WP','WDT','VB','NN','NNS','IN','DT']
##    spell = word[:word.index(":")]
##
##    tagged = nltk.pos_tag([spell])
##
##    type_word = total_type.index(tagged[0][1])+1
##    return type_word

##def two_prefix(word):
##    total = ["AA","AE","AH","AO","AW","AY","EH","ER","EY","IH","IY","OW","OY","UH","UW","P","B","CH","D","DH","F","G","HH","JH","K","L","M","N","NG","R","S","SH","T","TH","V","W","Y","Z","ZH"]
##    two_pronounce = word[word.index(":")+1:]
##    two_pronounce = two_pronounce.split()
##    first_prefix = 0
##    second_prefix = 0
##    first_prefix = total.index(two_pronounce[0][:2])+1
##    second_prefix = total.index(two_pronounce[1][:2])+1
##
##    return first_prefix,second_prefix
def two_vowel(word):
    total = ["AA","AE","AH","AO","AW","AY","EH","ER","EY","IH","IY","OW","OY","UH","UW"]
    two_pronounce = word[word.index(":")+1:]
    two_pronounce = two_pronounce.split()
    last_vowel = 0
    second_last_vowel = 0
    tiny_vow = []
    for ti in two_pronounce:
        if ti[:2] in total:
            tiny_vow.append(total.index(ti[:2])+1)
    last_vowel = tiny_vow[-1]
    second_last_vowel = tiny_vow[-2]*100
##    if last_vowel < 10:
##        last_vowel = "0"+str(last_vowel)
##    else:
##        last_vowel = str(last_vowel)
##    if second_last_vowel < 10:
##        second_last_vowel = "0" +str(second_last_vowel)
##    else:
##        second_last_vowel = str(second_last_vowel)
##    print(second_last_vowel+last_vowel)
    return second_last_vowel+last_vowel
##    second_prefix = total.index(two_pronounce[1][:2])+1
##
##    return first_prefix,second_prefix
def last(word,last_dic):
    spell = word[:word.index(":")]
    if spell[-1] == "S" or spell[-1] == "D":
        spell = spell[:-1]
    english_letter = ["A","B","C","D","E","F","G","H","I","G","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
    if len(spell) < 3:
        la = 0
    else:
        if spell[-3:] in last_dic:

            la = ((english_letter.index(spell[-3])+1)*100 +(english_letter.index(spell[-2])+1))*100+english_letter.index(spell[-1])+1
        else:
            la = 0
    return la
def three_letter(data):
    last_dic = {}
    dic_keys = []
    for word in data:
       spell = word[:word.index(":")]
       if spell[-1] == "S" or spell[-1] == "D":
           spell = spell[:-1]
       lastword = spell[-3:]
       if lastword in last_dic.keys():
           last_dic[lastword] += 1
       else:
           last_dic[lastword] = 1
    for ke in last_dic:
        dic_keys.append(ke)

    for clear in dic_keys:
        if last_dic[clear]<30:
            del last_dic[clear]

    return last_dic.keys()

def train(data, classifier_file):# do not change the heading of the function
    global last_dic
    vowel = ["AA","AE","AH","AO","AW","AY","EH","ER","EY","IH","IY","OW","OY","UH","UW"]
    consonant = ["P","B","CH","D","DH","F","G","HH","JH","K","L","M","N","NG","R","S","SH","T","TH","V","W","Y","Z","ZH"]
    instances = []
    attributes = ["two_vowel","vowel_num","combine","last_word","position"]
    features = ["two_vowel","vowel_num","combine","last_word"]
    firstvowel = 0
    secondvowel = 0
    thirdvowel = 0
    forthvowel = 0
    last_dic = three_letter(data)
    for word in data:
        tokens = []
        word_vowel = []
        type_word = 0
        first_prefix = 0
        second_prefix = 0
        pronounce = word[word.index(":")+1:]

        pronounce = pronounce.split()
        ## vowel_num feature
        vowel_number,word_vowel = vowel_num(pronounce)
        ## record exact vowel
##        firstvowel = first_vowel(pronounce)
##        secondvowel = second_vowel(pronounce)
##        thirdvowel = third_vowel(pronounce)
##        forthvowel = forth_vowel(pronounce)
        ## judge lastword
        lastword = last(word,last_dic)

        ## combine
        comb = combine(pronounce)
        ## generate last two vowels combine
        vowel_com = two_vowel(word)
        ## judge prefix
##        prefix,suffix = total_prefix(word)

        ## judge the type of the word
##        type_word = typeword(word)
##            first_prefix,second_prefix = two_prefix(word)
##            print(word)
##            print(type_word)
##            print(first_prefix)
##            print(second_prefix)

        ##get the stress position
        for tiny_pron in word_vowel:
            if "1" in tiny_pron:
                stress = word_vowel.index(tiny_pron)+1
##                print(stress)
##                print(pronounce)

        instances.append([vowel_com,vowel_number,comb,lastword,stress])

    df = pd.DataFrame(data=instances,columns = attributes)
    x = df[features]
    y = df.position
    x_train, x_test, y_train, y_test = model_selection.train_test_split(x,y, test_size = 0.2)
    clf = tree.DecisionTreeClassifier(criterion = 'entropy')

    model=clf.fit(x, y)
##    prediction = list(clf.predict(x_test))
##    ground_truth = list(y_test)
##    precision = [0,0,0,0]
##    count = [0,0,0,0]
##    for i in range(len(ground_truth)):
##        if ground_truth[i] == prediction[i]:
##           precision[ground_truth[i] - 1] +=1
##        count[ground_truth[i] - 1] += 1
##    for j in range(len(count)):
##        precision[j] = precision[j]/count[j]
##    print(count)
##    print(precision)
##    print(f1_score(ground_truth,prediction,average = 'macro'))
    output = open(classifier_file,'wb')
    pickle.dump(clf,output)
    output.close()

################# testing #################

def test(data, classifier_file):# do not change the heading of the function
    global last_dic
    clf = pickle.load(open(classifier_file,"rb"))
    vowel = ["AA","AE","AH","AO","AW","AY","EH","ER","EY","IH","IY","OW","OY","UH","UW"]
    consonant = ["P","B","CH","D","DH","F","G","HH","JH","K","L","M","N","NG","R","S","SH","T","TH","V","W","Y","Z","ZH"]
    instances = []
    attributes = ["two_vowel","vowel_num","combine","last_word","position"]
    features = ["two_vowel","vowel_num","combine","last_word"]

    for word in data:
        tokens = []
        word_vowel = []
        type_word = 0
        first_prefix = 0
        second_prefix = 0
        pronounce = word[word.index(":")+1:]

        pronounce = pronounce.split()
        ## vowel_num feature
        vowel_number,word_vowel = vowel_num(pronounce)
        ## judge lastword
        lastword = last(word,last_dic)
##        print(lastword)
        ## combine
        comb = combine(pronounce)
        ## generate last two vowels combine
        vowel_com = two_vowel(word)
        ## judge prefix
##        prefix,suffix = total_prefix(word)
        ## type of the word
##        type_word = typeword(word)

        instances.append([vowel_com,vowel_number,comb,lastword])
    df = pd.DataFrame(data=instances,columns = features)
    x = df[features]

    prediction = list(clf.predict(x))
    return prediction

##
##if __name__ == '__main__':
##
##    training_data = helper.read_data('./asset/training_data.txt')
##    classifier_path = './asset/classifier.dat'
##    train(training_data,classifier_path)
##    test_data = helper.read_data('./asset/tiny_test.txt')
##    prediction = test(test_data,classifier_path)
##    print(prediction)
##

##


import os
import sys
from datetime import datetime

from airflow import DAG
from airflow.exceptions import AirflowFailException, AirflowSkipException
from airflow.operators.dummy import DummyOperator
from airflow.operators.python import PythonOperator
from airflow.providers.google.cloud.transfers.gcs_to_gcs import GCSToGCSOperator
from google.cloud import bigquery
from airflow.providers.google.cloud.operators.bigquery import BigQueryInsertJobOperator
from dags.common.query_utils import query_utils
from dags.common.utils import get_default_args
from dags.dag_configs.file_export_configs import file_export_configs
from dags.dag_configs.variables import *

query_utils = query_utils()

def fetch_last_exported_date(**kwargs):
    return

def check_record_count(**kwargs):
    return

def insert_cdc_details(**kwargs):
    return

def create_dag(config):
    default_args = get_default_args(retries=1)

    dag_id = "{}_export".format(config['source_table_name'])

    return DAG(dag_id=dag_id,
               default_args=default_args,
               schedule_interval= config['schedule_interval'],
               tags=["bq_gcs_export"]
            )

for export_config in file_export_configs:
    dag = create_dag(export_config)
    globals()[dag.dag_id] = dag

    # variables
    source_table_name = export_config['source_table_name']
    export_format = export_config['export_format']
    load_type = export_config['load_type']
    cdc_column_name = export_config['cdc_column'] if load_type == "DELTA" else ''

    # start building task
    start_export = DummyOperator(task_id="start_task", dag=dag)
    end_export = DummyOperator(task_id="end_task", dag=dag)

    # Step1: Move files from active to archive
    move_file_archive = GCSToGCSOperator(
        task_id="move_to_archive",
        source_bucket=GCP_SHARED_DESTINATION_BUCKET_NAME,
        source_object="active/" + source_table_name,
        destination_bucket=GCP_SHARED_DESTINATION_BUCKET_NAME,
        destination_object="archive/" + source_table_name,
        move_object=True,
        gcp_conn_id=GCP_CONN_STRING,
        dag=dag
    )

    # Step2: Get last export date from CDC master for source table
    fetch_last_export_date = PythonOperator(
        task_id="fetch_last_export_date",
        python_callable=fetch_last_exported_date,
        op_kwargs={
            "google_cloud_conn_id": GCP_CONN_STRING,
            "query": """SELECT MAX(last_export_datetime) as last_export_datetime FROM output.change_data_capture_audit
            WHERE source_table_name=@source_table_name""",
            "source_table_name": source_table_name
        },
        provide_context=True,
        dag=dag
    )

    check_count = PythonOperator(
        task_id="check_count",
        python_callable=check_record_count,
        op_kwargs={
            "google_cloud_conn_id": GCP_CONN_STRING,
            "source_table_name": source_table_name,
            "load_type": load_type,
            "cdc_column": cdc_column_name
        },
        provide_context=True,
        dag=dag
    )

    export_bq_to_gcs = BigQueryInsertJobOperator(
         task_id='export_bq_to_gcs',
         configuration={
             "query": {
                 "query": query_utils.create_cdc_export_query(
                     PROJECT_ID,
                     GCP_CONN_STRING,
                     source_table_name,
                     cdc_column_name,
                     export_format
                 ),
                 "allow_large_results": True,
                 "useLegacySql": False,
             }
         },
         gcp_conn_id=GCP_CONN_STRING,
         dag=dag
     )

    update_cdc_master = PythonOperator(
        task_id='update_cdc_master',
        python_callable=insert_cdc_details,
        op_kwargs={
            "google_cloud_conn_id": GCP_CONN_STRING,
            "source_table_name": source_table_name,
            "load_type": load_type,
            "cdc_column": cdc_column_name

        },
        provide_context=True,
        do_xcom_push=False,
        dag=dag
    )

    start_export >> move_file_archive >> fetch_last_export_date >> check_count >> export_bq_to_gcs >> update_cdc_master >> end_export


import torch
import torch.nn as nn
from torch.nn import Parameter
import torch.nn.functional as F
from models.layers import (
    GraphAttentionLayer,
    SpGraphAttentionLayer,
    EdgeGraphAttentionLayer
)

DEVICE = torch.device('cuda' if torch.cuda.is_available() else 'cpu')

class GAT(nn.Module):
    def __init__(self, nfeat, nhid, nclass, dropout, alpha, nheads):
        """Dense version of GAT."""
        super(GAT, self).__init__()
        self.dropout = dropout

        self.attentions = [GraphAttentionLayer(nfeat, nhid, dropout=dropout, alpha=alpha, concat=True) for _ in range(nheads)]
        for i, attention in enumerate(self.attentions):
            self.add_module('attention_{}'.format(i), attention)

        self.out_att = GraphAttentionLayer(nhid * nheads, nclass, dropout=dropout, alpha=alpha, concat=False)

    def forward(self, x, adj):
        x = F.dropout(x, self.dropout, training=self.training)
        x = torch.cat([att(x, adj) for att in self.attentions], dim=1)
        x = F.dropout(x, self.dropout, training=self.training)
        x = F.elu(self.out_att(x, adj))
        return F.log_softmax(x, dim=1)

class SpGAT(nn.Module):
    def __init__(self, nfeat, nhid, nclass, dropout, alpha, nheads):
        """Sparse version of GAT."""
        super(SpGAT, self).__init__()
        self.dropout = dropout

        self.attentions = [SpGraphAttentionLayer(nfeat,
                                                 nhid,
                                                 dropout=dropout,
                                                 alpha=alpha,
                                                 concat=True) for _ in range(nheads)]
        for i, attention in enumerate(self.attentions):
            self.add_module('attention_{}'.format(i), attention)

        self.out_att = SpGraphAttentionLayer(nhid * nheads,
                                             nclass,
                                             dropout=dropout,
                                             alpha=alpha,
                                             concat=False)

    def forward(self, x, adj):
        x = F.dropout(x, self.dropout, training=self.training)
        x = torch.cat([att(x, adj) for att in self.attentions], dim=1)
        x = F.dropout(x, self.dropout, training=self.training)
        x = F.elu(self.out_att(x, adj))
        return F.log_softmax(x, dim=1)

class EGAT(nn.Module):
    def __init__(self, node_feat, edge_feat, nclass, nhidden, dropout, alpha, nheads):
        super(EGAT, self).__init__()
        self.dropout = dropout
        self.linear = nn.Linear(edge_feat, 1)

        self.attentions = [GraphAttentionLayer(\
            node_feat, nhidden, dropout=dropout, alpha=alpha, concat=True) for _ in range(nheads)]
        for i, attention in enumerate(self.attentions):
            self.add_module('attention_{}'.format(i), attention)

        self.out_att = GraphAttentionLayer(\
            nhidden * nheads, nhidden, dropout=dropout, alpha=alpha, concat=False)

        self.fc = nn.Sequential(
            nn.Dropout(p=dropout),
            nn.Linear(nhidden, nhidden // 2),
            nn.Dropout(p=dropout),
            nn.Linear(nhidden // 2, nclass)
        )

        self.activation = nn.LeakyReLU(alpha)

    def forward(self, in_data):
        """ Node embedding - Edge embedding """
        node_fts_txt = in_data['node_fts_txt'].to(DEVICE)
        node_fts_loc = in_data['node_fts_loc'].to(DEVICE)

        node_fts = node_fts_txt
        edge_fts = in_data['edge_fts'].to(DEVICE)

        edges = self.linear(edge_fts).squeeze(-1)
        edges = F.elu(edges)

        nodes = F.dropout(node_fts, self.dropout, training=self.training)
        edges = F.dropout(edges, self.dropout, training=self.training)

        x = torch.cat([att(nodes, edges) for att in self.attentions], dim=-1)
        x = F.dropout(x, self.dropout, training=self.training)

        x = F.elu(self.out_att(x, edges))
        x = torch.max(x, dim=1)[0]
        x = self.fc(x)
        x = self.activation(x)

        return F.log_softmax(x, dim=1)


from tkinter import *
import sqlite3
from tkinter import messagebox
import os
class doctor_page:
    #from photo import pic
    def __init__(self,master):
        self.doidv=StringVar()
        self.spe=StringVar()
        self.medicines=StringVar()
        self.tests=StringVar()
        self.master = master
        self.top=Frame(master,width=1300,height=100,bg='lightgreen')
        self.top.pack(side=TOP)
        self.left = Frame(master, width=1300, height=90, bg='lightblue')
        self.left.pack(side=TOP)
        self.right = Frame(master, width=1300, height=520, bg='lightyellow')
        self.right.pack(side=RIGHT)
        head=Label(self.top,text='E-HEALTH CARE CENTER',font=('Times_New_Roman 30 bold'), fg='red', bg='lightgreen')
        head.place(x=400,y=0)

        Welmsg=Label(self.right,text='Welcome to E-HEALTH CARE CENTER',font=('Times_New_Roman 40 bold'), fg='red', bg='lightyellow')
        Welmsg.place(x=90,y=200)

        remdet=Button(self.left,text='Click_to_EXIT',height=5,width=65,command=master.destroy,fg='red')
        remdet.place(y=0,x=850)
    def buttonact(self):
        presc=Button(self.left,text='Click_to_message_patient',height=5,width=60,command=self.message,fg='red')
        presc.place(y=0,x=450)
        #addet=Button(self.left,text='Click_to_show_all_doctor',height=5,width=27)#,command=self.showdet)
        #addet.place(y=0,x=85)
        upd=Button(self.left,text='Click_to_Prepare_Report',height=5,width=65,command=self.linkwitdoctor,fg='red')
        upd.place(y=0,x=0)
##########################  Function to link view all requests by patients ######################################
    def linkwitdoctor(self):
        for widget in self.right.winfo_children():
            widget.destroy()
        '''conn=sqlite3.connect('hos.db')
        c=conn.cursor()
        records=c.fetchall()'''
        #self.displaypat()
        self.ptid=IntVar()
        self.doid=IntVar()
        #self.pat=Entry(self.right,textvariable=self.ptid)
        #self.pat.place(x=100,y=100)
        l1=Label(self.right,text="Enter your ID here:", bg='lightyellow')
        l1.place(x=10,y=100)
        self.docid=Entry(self.right,textvariable=self.doid)
        self.docid.place(x=300,y=100)
        butt=Button(self.right,text="CLICK TO VIEW ALL REQUESTS",command=self.displaypat,width=50)
        butt.place(x=100,y=200,height=50)
#########################        PLAN CHANGE ####################################################
    def link1(self):
        print(self.ptid.get())
        self.stat=0
        l1=[]
        l1.append(self.ptid.get())
        l1.append(self.doid.get())
        l1.append(self.medicines.get())
        l1.append(self.tests.get())
        #l1.append(self.stat)
        l1=tuple(l1)
        l2=[]
        l2.append(l1)
        print(l2)

        conn=sqlite3.connect('hos.db')
        c=conn.cursor()
        c.execute('''DROP TABLE docpat''')
        c.execute('''CREATE TABLE docpat (dodidv int ,patid int,medicines text,tests text)''')
        c.executemany('''INSERT INTO docpat values(?,?,?,?,?)''',l2)
        conn.commit()
        messagebox.showinfo("SUCESS","DOCTOR "+ " Connected to patient" )
        conn.close()
######################### THIS IS THE INTER FACE WHERE THE DOCTOR PREPARES PRESCRIPTION FOR THE PATIENT ###################################################
    def link2(self):
        for widget in self.right.winfo_children():
            widget.destroy()
        lb1=Label(self.right,text="Enter patient id: ", bg='lightyellow')
        lb1.place(x=10,y=100)
        self.pat=Entry(self.right,textvariable=self.ptid)
        self.pat.place(x=200,y=100)
        print(self.ptid.get())
        self.medc=StringVar()
        self.tests=StringVar()
        #st=int(1)
        #l1=[]
        l1=Label(self.right,text="Enter Medicine", bg='lightyellow')
        l1.place(x=100,y=150)
        self.med=Entry(self.right,textvariable=self.medc,width=100)
        self.med.place(x=100,y=200,height=100)
        #l1.append(st)
        l1=Label(self.right,text="Enter Tests to be performed", bg='lightyellow')
        l1.place(x=100,y=310)
        self.tes=Entry(self.right,textvariable=self.tests,width=100)
        self.tes.place(x=100,y=350,height=100)
        #l1.append(st)
        butt=Button(self.right,text="Click to generate report",command=self.upd)
        butt.place(x=100,y=50)
#######################  MEDICINES AND TESTS HAVE BEEN ADDED TO THE DATABASE ########################33
    def upd(self):
        l1=[]
        l1.append(self.medc.get())
        l1.append(self.ptid.get())
        data=tuple(l1)
        conn=sqlite3.connect('hos.db')
        c=conn.cursor()
        tata = """UPDATE docpat set medicines=? where patid=?"""
        c.execute(tata,data)
        conn.commit()
        l1=[]
        l1.append(self.tests.get())
        l1.append(self.ptid.get())
        data=tuple(l1)
        tata = """UPDATE docpat set tests=? where patid=?"""
        c.execute(tata,data)
        conn.commit()
        messagebox.showinfo("SUCESS","DOCTOR "+ " Connected to patient" )
        conn.close()
##########################  THIS FUNCTION DISPLAYS ALL PATIENTS WHO HAVE MADE REQUEST TO THE DOCTOR
    def displaypat(self):
        for widget in self.right.winfo_children():
            widget.destroy()
        conn=sqlite3.connect('hos.db')
        c=conn.cursor()
        l1=[]
        l1.append(self.doid.get())
        data=tuple(l1)
        tata="""SELECT * from docpat where dodidv=?"""
        c.execute(tata,data)
        records=c.fetchall()
        print(records)
        pos=0
        wid=15
        l1=Label(self.right,text='doid',font=('Times_New_Roman 15 bold'), fg='red', bg='blue',width=10)
        l1.place(x=0,y=10+pos)
            #t1=Text(self.right,=p_rec)
            #t1.pack()
        l2=Label(self.right,text='patid',font=('Times_New_Roman 15 bold'), fg='red', bg='lightyellow',width=wid)
        l2.place(x=100,y=10+pos)
        l3=Label(self.right,text='medicines',font=('Times_New_Roman 15 bold'), fg='red', bg='lightyellow',width=wid+20)
        l3.place(x=300,y=10+pos)
        l4=Label(self.right,text='tests',font=('Times_New_Roman 15 bold'), fg='red', bg='lightyellow',width=wid+20)
        l4.place(x=800,y=10+pos)
        #l5=Label(self.right,text='status',font=('Times_New_Roman 15 bold'), fg='red', bg='orange',width=wid)
        #l5.place(x=700,y=10+pos)
        #l6=Label(self.right,text='status',font=('Times_New_Roman 15 bold'), fg='red', bg='brown',width=wid)
        #l6.place(x=900,y=10+pos)
        count=0
        pos=40
        wid=15
        for record in records:
            #p_rec=''
            #p_rec += str(record[0])+"  "+ str(record[1])+"  "+ str(record[2])+"  "+ str(record[3])+"  "+ str(record[4])+"  "+ str(record[5])+"\n"
            l1=Label(self.right,text=record[0],font=('Times_New_Roman 15 bold'), fg='red', bg='blue',width=10)
            l1.place(x=0,y=10+pos)
            #t1=Text(self.right,=p_rec)
            #t1.pack()
            l2=Label(self.right,text=record[1],font=('Times_New_Roman 15 bold'), fg='red', bg='lightyellow',width=wid)
            l2.place(x=100,y=10+pos)
            l3=Label(self.right,text=record[2],font=('Times_New_Roman 15 bold'), fg='red', bg='lightyellow',width=wid+20)
            l3.place(x=300,y=10+pos)
            l4=Label(self.right,text=record[3],font=('Times_New_Roman 15 bold'), fg='red', bg='lightyellow',width=wid+20)
            l4.place(x=800,y=10+pos)
            count=count+1
            pos=pos+40
        conn.close()
        butt=Button(self.right,text="Click here to generate report",command=self.link2,width=50)
        butt.place(x=900,y=450,height=70)
###################### DOCOTR CAN COMMUNICATE WITH PATIENT  ###############################
    def message(self):
        for widget in self.right.winfo_children():
            widget.destroy()
        self.reply=StringVar()
        rep=Entry(self.right,textvariable=self.reply,width=100)
        rep.place(x=500,y=150,height=100)
        self.lb2=Label(self.right,text='Enter your reply: ', bg='lightyellow')
        self.lb2.place(x=500,y=100)
        self.lb1=Label(self.right,text='', bg='lightyellow')
        self.lb1.place(x=500,y=300)
        send=Button(self.right,text="send",command=self.writefile)
        send.place(x=10,y=300)
        self.dno=StringVar()
        self.pno=IntVar()
        self.lb2=Label(self.right,text='Enter doctor name: ', bg='lightyellow')
        self.lb2.place(x=0,y=100)
        dname=Entry(self.right,textvariable=self.dno)
        dname.place(x=200,y=100)
        self.lb3=Label(self.right,text='Enter patient id: ', bg='lightyellow')
        self.lb3.place(x=0,y=200)
        pname=Entry(self.right,textvariable=self.pno)
        pname.place(x=200,y=200)
        send=Button(self.right,text="End conversation",command=self.endc)
        send.place(x=100,y=300)
        rec=Button(self.right,text="Recieve reply",command=self.read)
        rec.place(x=300,y=300)
    def writefile(self):
        #for widget in self.right.winfo_children():
         #   widget.destroy()
        self.name=str(self.dno.get())+str(self.pno.get())+".txt"
        print(self.name)
        try:
            f=open(self.name,"r")
            val=f.read()
            self.pos=0
            self.lb1.config(text=val)
            f.close
        except FileNotFoundError:
            val=("doctor: "+self.reply.get())
            f=open(self.name,"w")
            print(f.write(val))
        #print(f.write(rangenge(0,10)))
        val=("doctor: "+self.reply.get())
        f=open(self.name,"w")
        print(f.write(val))
        f.close()
        f=open(self.name,"r")
        val=f.read()
        self.pos=0
        self.lb1.config(text=val)
        f.close
    def read(self):
        f=open(self.name,"r")
        val=f.read()
        self.pos=0
        self.lb1.config(text=val)
        f.close
    def endc(self):
        os.remove(self.name)
root=Tk()
root.geometry('1300x720+0+0')
root.resizable(False,False)
root.title('Doctor Interface')
#presc=Button(root,text='click_to_message_patient',height=5,width=65,command=showimg)
#presc.pack()
ob1=doctor_page(root)
ob1.buttonact()
#ob1.display()

root.mainloop()


# Author:   Adam Anderson
# Date:     Jan 5, 2015
# Updated:  Jan 21, 2016
# Python:   3.4.0+

from common import msg_header
import socket
import sys
import threading
import tkinter as tk

# Server Parameters
HOST = "localhost"
PORT = 55601

class Client(object):

    def __init__(self):
        self.name = "Me"

        self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.socket.setblocking(True)
        self.display = ClientDisplay(self.connect, self.send_message)
        self.display.launch()

    def connect(self, host, port):
        try:
            print("connecting.")
            self.socket.connect((host, port))
        except socket.error:
            print("Unable to connect to server:  ", host, ":", port)
            sys.exit()

        # Listen for incoming messages
        threading.Thread(target=self.receive).start()

    def receive(self):
        print("Started listening thread.")
        while True:
            try:
                if self.socket is not None:
                    message = self.socket.recv(1500).decode()
                    self.display.show_incoming_msg(message)
            except OSError as msg:
                print("Socket error 1.  :(")
                break

    def send_message(self, message):
        self.socket.send(message.encode())
        if message == "/quit":
            print("i have quit")
            self.socket.close()
            self.display.show_incoming_msg("Disconnected from server.")

class ClientDisplay(object):

    def __init__(self, connect_function, msg_sender):
        self.connect_function = connect_function
        self.msg_sender = msg_sender

        self.root = tk.Tk()
        main_frame = tk.Frame(self.root)
        self.root.wm_title("datchat v1.0")

        # IP Field
        ip_label = tk.Label(main_frame, text="Server IP:").grid(row=0, column=0, padx=2, pady=2, sticky=tk.E)
        self.ip_field = tk.Entry(main_frame)
        self.ip_field.grid(row=0, column=1, padx=2, pady=2, sticky=(tk.N, tk.S, tk.W, tk.E))
        self.ip_field.insert(tk.END, HOST)

        # Port Field
        port_label = tk.Label(main_frame, text="Server Port:").grid(row=0, column=2, padx=2, pady=2, sticky=tk.E)
        self.port_field = tk.Entry(main_frame)
        self.port_field.grid(row=0, column=3, padx=2, pady=2, sticky=(tk.N, tk.S, tk.W, tk.E))
        self.port_field.insert(tk.END, str(PORT))

        # Connect Button
        self.connect_button = tk.Button(main_frame, text="Connect", command=self.connect)
        self.connect_button.grid(row=0, column=4, padx=2, pady=2, sticky=(tk.N, tk.S, tk.W, tk.E))

        # Chat Area
        self.chat_area = tk.Text(main_frame)
        self.chat_area.grid(row=1, column=0, columnspan=5, padx=2, pady=2)

        # Chat Entry
        self.msg_entry = tk.Entry(main_frame)
        self.msg_entry.grid(row=5, column=0, columnspan=4, padx=2, pady=2, sticky=(tk.N, tk.S, tk.W, tk.E))
        self.msg_entry.bind('<Return>', self.__send_message)

        # Send Button
        self.send_button = tk.Button(main_frame, text="Send", command=self.__send)
        self.send_button.grid(row=5, column=4, padx=2, pady=2, sticky=(tk.N, tk.S, tk.W, tk.E))

        main_frame.grid(row=0, column=0)

    def launch(self):
        self.root.mainloop()

    def connect(self):
        host = self.ip_field.get()
        port = int(self.port_field.get())
        print("Connecting to server(", host, " on port number", port)
        self.connect_function(host, port)

    def show_incoming_msg(self, message):
        self.chat_area.insert(tk.END, message)
        self.chat_area.insert(tk.END, "\n")
        self.chat_area.yview(tk.END)

    def __send(self):
        self.__send_message(None)

    def __send_message(self, button):
        message = self.msg_entry.get()
        self.msg_sender(msg_header + message)
        self.msg_entry.delete(0, tk.END)


from typing import List
from starlette.requests import Request
from fastapi import FastAPI, File
from starlette.templating import Jinja2Templates
import uvicorn

app = FastAPI()
template = Jinja2Templates(directory='templates')

@app.get('/')
async def index(request:Request):
    return template.TemplateResponse(
        'form_for_upload.html',
        context={
            'request':request,
        }
    )

# @app.post('/files/')
# async def create_file(request:Request, file1:bytes=File(...)):
#     return {'request':request,'file_size':len(file1)}

@app.post('/files/')
async def create_many_files(file1: List[bytes] = File(...)):
    return {
        'message': [len(i) for i in file1],
    }

if __name__ == '__main__':
    uvicorn.run(app=app,host='127.0.0.1', port=8000)


import sys
from pathlib import Path
from os.path import dirname, realpath
script_dir = Path(dirname(realpath(__file__)))
module_dir = str(script_dir.parent)
sys.path.insert(0, module_dir + '/modules')
sys.path.insert(0, module_dir + '/models')

import tensorflow as tf
import numpy as np
import armm_ps as ps
import armm_sp as sp
import nnplot as nnp

r = 5.0
space_x = r * np.array([-1., 1.])
space_y = r * np.array([-1., 1.])
time_ = [0.0, 10.0]

armmb = sp.ArMmSpBlock(dim = 2, time_dependent = False)
mu = [(-2.,), (2.,), (-4.,)]
sigma = [(0.,), (0.,), (0.,)]

nn = sp.ArMmSp(num_components = 3, dim = 7, num_nodes=1, num_layers = 1, time_dependent = True, param_inits=None)
#print(nn.armmbs[0].__dict__['param_0_0'])#, 'param_0_0' + '_b_f'))
"""
plotter = nnp.NNPlotter(funcs=[armmb], space=[space_x], num_pts_per_dim=100)
plotter.plot(file_path='../../images/ArMmSpBlock1d.png')
#"""

x = []
for i in range(armmb.dim):
    x.append(tf.convert_to_tensor(np.random.uniform(low=0., high=1., size = (10, 1)), dtype=tf.float32))
print(armmb(*x))
x = []
for i in range(nn.dim):
    x.append(tf.convert_to_tensor(np.random.uniform(low=0., high=1., size = (10, 1)), dtype=tf.float32))
print(nn.armmbs[0](*x))
print(nn.armmbs[1](*x))
print(nn(*x))
"""
plotter = nnp.NNPlotter(funcs=[nn], space=[space_x, space_y], num_pts_per_dim=50)
plotter.plot(file_path='../../images/armmsp_circleNN.png')
#"""
# integration test
nn.add_domain([time_, space_x, space_y])
num_pts = 10000
t, x, y = nn.domain_sampler(0, num_pts)
print(tf.math.reduce_sum(nn(tf.ones_like(x), x, y)))


import nextcord
from nextcord.ext import commands, application_checks
from datetime import datetime

import sys
import os
path = os.getcwd()
sys.path.append('../bot')

from util.loaders.yml import read_yml

config = read_yml('config/config')

class Moderation(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    def userinfo_cmd():
        @nextcord.slash_command(description="Show information about the user")
        @application_checks.has_permissions(administrator=True)
        async def userinfo(self, ctx, user: nextcord.Member):
            if user == None:
                user = ctx.user
            author = ctx.user
            date_format = "%a, %d %b %Y %I:%M %p"
            em = nextcord.Embed()
            em.set_author(name=f"User-{user}")
            em.add_field(name="Registered", value=user.created_at.strftime(date_format))
            em.add_field(name="Joined on", value=user.joined_at.strftime(date_format))
            em.add_field(name="ID", value=user.id)
            if len(user.roles) > 1:
                role_string = ' '.join([r.mention for r in user.roles][1:])
                em.add_field(name="Roles [{}]".format(len(user.roles)-1), value=role_string, inline=False)
            perm_string = ', '.join([str(p[0]).replace("_", " ").title() for p in user.guild_permissions if p[1]])
            em.add_field(name="Guild permissions", value=perm_string, inline=False)
            await ctx.send(embed=em, ephemeral=True)
            self.bot.dispatch('userinfo', user, author)
            return

        @userinfo.error
        async def on_userinfo_error(self, interaction: nextcord.Interaction, error):
            if isinstance(error, application_checks.ApplicationMissingPermissions):
                embed = nextcord.Embed(title="Insufficient perms", description="You do not have the right permissions to run this comand.")
                await interaction.response.send_message(embed=embed, ephemeral=True)
            else:
                raise error

    def purge_cmd():
        @nextcord.slash_command(description="Delete a several messages at once")
        @application_checks.has_permissions(manage_messages=True)
        async def purge(self, ctx, ammount: int):
                embed = nextcord.Embed(
                title="Cleared", description=f"You cleared {ammount} messages")
                channel = ctx.channel
                author = ctx.user
                await ctx.channel.purge(limit=ammount)
                await ctx.send(embed=embed, ephemeral=True)
                self.bot.dispatch('purge', ammount, channel, author)

        @purge.error
        async def on_purge_error(self, interaction: nextcord.Interaction, error):
            if isinstance(error, application_checks.ApplicationMissingPermissions):
                embed = nextcord.Embed(title="Insufficient perms", description="You do not have the right permissions to run this comand.")
                await interaction.response.send_message(embed=embed, ephemeral=True)
            else:
                raise error

    def ban_cmd():
        @nextcord.slash_command(description="Bans a user")
        @application_checks.has_permissions(ban_members=True)
        async def ban(self, ctx, member: nextcord.Member, *, reason=None):
            author=ctx.user
            if reason == None:
                reason = "No reason provided"
            await member.ban(reason=reason)
            embed = nextcord.Embed(
                title="Ban", description=f"Banned {member.mention}.", color=nextcord.Color.from_rgb(3, 200, 255))
            await ctx.send(embed=embed, delete_after=5)
            self.bot.dispatch('ban', member, author, reason, self)

        @ban.error
        async def on_ban_error(self, interaction: nextcord.Interaction, error):
            if isinstance(error, application_checks.ApplicationMissingPermissions):
                embed = nextcord.Embed(title="Insufficient perms", description="You do not have the right permissions to run this comand.")
                await interaction.response.send_message(embed=embed, ephemeral=True)
                self.bot.dispatch('command', interaction.channel, interaction.author, suck="failed to", name="ban")
            else:
                raise error

        @commands.Cog.listener()
        async def on_ban(member, author, reason, self):
            logs = self.bot.get_channel(config["Logs"]["Logs-Channel-Name"])
            embed = nextcord.Embed(
                title="Ban command!", description=f"{author} banned {member} reason {reason}", color=nextcord.Color.blue())
            embed.timestamp = datetime.now()
            await logs.send(embed=embed)

    def unban_cmd():
        @nextcord.slash_command(description="Unbans the selected user")
        @application_checks.has_permissions(ban_members=True)
        async def unban(self, ctx, *, member):
            author=ctx.user
            banned_users = await ctx.guild.bans()
            member_name, member_discriminator = member.split('#')
            for ban_entry in banned_users:
                user = ban_entry.user
                if(user.name, user.discriminator) == (member_name, member_discriminator):
                    await ctx.guild.unban(user)
                    embed = nextcord.Embed(
                        title="Unbanned", description=f"Unbanned {user.name}#{user.discriminator}", color=nextcord.Color.from_rgb(0, 255, 0))
                    await ctx.send(embed=embed)
                    return
            self.bot.dispatch('unban', member, author, self)

        @unban.error
        async def on_unban_error(self, interaction: nextcord.Interaction, error):
            if isinstance(error, application_checks.ApplicationMissingPermissions):
                embed = nextcord.Embed(title="Insufficient perms", description="You do not have the right permissions to run this comand.")
                await interaction.response.send_message(embed=embed, ephemeral=True)
            else:
                raise error

        @commands.Cog.listener()
        async def on_unban(self, member, author):
            logs = self.bot.get_channel(config["Logs"]["Logs-Channel-Name"])
            embed = nextcord.Embed(
                title="User unbanned!", description=f"{author} unbanned {member}", color=nextcord.Color.blue())
            embed.timestamp = datetime.now()
            await logs.send(embed=embed)

    def kick_cmd():
        @nextcord.slash_command(description="Kick the selcted user")
        @application_checks.has_permissions(kick_members=True)
        async def kick(self, ctx, member: nextcord.Member, *, reason=None):
            if reason == None:
                reason = "No reason provided"
            await ctx.guild.kick(member)
            channel = ctx.channel
            await channel.purge(limit=1)
            embed = nextcord.Embed(title="Kick", description=f"Kicked {member.mention}.", color=nextcord.Color.from_rgb(255, 0, 0))
            embed.add_field(title="Reason:", value=reason)
            await ctx.send(embed=embed, ephemeral=True)

        @kick.error
        async def on_purge_error(self, interaction: nextcord.Interaction, error):
            if isinstance(error, application_checks.ApplicationMissingPermissions):
                embed = nextcord.Embed(title="Insufficient perms", description="You do not have the right permissions to run this comand.")
                await interaction.response.send_message(embed=embed, ephemeral=True)
            else:
                raise error

        @commands.Cog.listener()
        async def on_purge(self, ammount, channel, author):
            logs = self.bot.get_channel(config["Logs"]["Logs-Channel-Name"])
            embed = nextcord.Embed(title="Messages cleared", description=f"{author.mention} deleted messages")
            embed.add_field(name="Ammount: ", value=ammount)
            embed.add_field(name="Channel: ", value=channel.mention)
            embed.timestamp = datetime.now()
            await logs.send(embed=embed)

    def mute_cmd():
        @nextcord.slash_command(description="Mutes the selected user")
        @application_checks.has_permissions(manage_messages=True)
        async def mute(self, ctx, member: nextcord.Member, *, reason=None):
            guild = ctx.guild
            mutedRole = nextcord.utils.get(guild.roles, name="Muted")
            if not mutedRole:
                mutedRole = await guild.create_role(name="Muted")
                for channel in guild.channels:
                    await channel.set_permissions(mutedRole, speak=False, send_messages=False, read_message_history=True, read_messages=False)
            await member.add_roles(mutedRole, reason=reason)
            await ctx.send(f"Muted {member.mention} for reason {reason}")
            await member.send(f"You were muted in the server {guild.name} for {reason}")

        @mute.error
        async def on_mute_error(self, interaction: nextcord.Interaction, error):
            if isinstance(error, application_checks.ApplicationMissingPermissions):
                embed = nextcord.Embed(title="Insufficient perms", description="You do not have the right permissions to run this comand.")
                await interaction.response.send_message(embed=embed, ephemeral=True)
            else:
                raise error

        @commands.Cog.listener()
        async def on_purge(self, ammount, channel, author):
            logs = self.bot.get_channel(config["Logs"]["Logs-Channel-Name"])
            embed = nextcord.Embed(title="Messages cleared", description=f"{author.mention} deleted messages")
            embed.add_field(name="Ammount: ", value=ammount)
            embed.add_field(name="Channel: ", value=channel.mention)
            embed.timestamp = datetime.now()
            await logs.send(embed=embed)

    def unmute_cmd():
        @nextcord.slash_command(description="Unmutes the selected user")
        @application_checks.has_permissions(manage_messages=True)
        async def unmute(self, ctx, member: nextcord.Member):
            author = ctx.author
            mutedRole = nextcord.utils.get(ctx.guild.roles, name="Muted")
            await member.remove_roles(mutedRole)
            await ctx.send(f"Unmuted {member.mention}", ephemeral=True)
            await member.send(f"You have been unmuted in {ctx.guild.name}")
            self.bot.dispatch('unmute', member, author)

        @unmute.error
        async def on_unmute_error(self, interaction: nextcord.Interaction, error):
            if isinstance(error, application_checks.ApplicationMissingPermissions):
                embed = nextcord.Embed(title="Insufficient perms", description="You do not have the right permissions to run this comand.")
                await interaction.response.send_message(embed=embed, ephemeral=True)
            else:
                raise error

        @commands.Cog.listener()
        async def on_unmute(self, member, author):
            logs = self.bot.get_channel(config["Logs"]["Logs-Channel-Name"])
            embed = nextcord.Embed(title="Member unmuted", description=f"{author.mention} unmuted {member.mention}")
            embed.timestamp = datetime.now()
            await logs.send(embed=embed)

def setup(bot):
    bot.add_cog(Moderation(bot))