def meanOrderFrequency(path_to_dataset):
    """
    Displays the mean order frequency by utilizing the orders table.
    :param path_to_dataset: this path should have all the .csv files for the dataset
    :type path_to_dataset: str
    """
    assert isinstance(path_to_dataset, str)
    import pandas as pd
    order_file_path = path_to_dataset + '/orders.csv'
    orders = pd.read_csv(order_file_path)
    print('On an average, people order once every ', orders['days_since_prior_order'].mean(), 'days')

def numOrdersVsDays(path_to_dataset):
    """
    Displays the number of orders and how this number varies with change in days since last order.
    :param path_to_dataset: this path should have all the .csv files for the dataset
    :type path_to_dataset: str
    """

    assert isinstance(path_to_dataset, str)

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

    order_file_path = path_to_dataset + '/orders.csv'

    orders = pd.read_csv(order_file_path)

    order_by_date = orders.groupby(by='days_since_prior_order').count()

    fig = plt.figure(figsize = [15, 7.5])
    ax = fig.add_subplot()
    order_by_date['order_id'].plot.bar(color = '0.75')
    ax.set_xticklabels(ax.get_xticklabels(), fontsize= 15)
    plt.yticks(fontsize=16)
    ax.get_xaxis().set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x))))
    ax.get_yaxis().set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x/1000))))
    ax.set_xlabel('Days since previous order', fontsize=16)
    ax.set_ylabel('Number of orders / 1000', fontsize=16)
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.get_children()[7].set_color('0.1')
    ax.get_children()[14].set_color('0.1')
    ax.get_children()[21].set_color('0.1')
    ax.get_children()[30].set_color('0.1')
    my_yticks = ax.get_yticks()
    plt.yticks([my_yticks[-2]], visible=True)
    plt.xticks(rotation = 'horizontal');

def numOrderDaysSizeBubble(path_to_dataset):
    """
    Plots a bubble plot in which:
    x: Days since Previous Order
    y: Number of orders/1000
    size: Average Size of order given it was placed on x

    :param path_to_dataset: this path should have all the .csv files for the dataset
    :type path_to_dataset: str
    """
    import numpy as np
    import pandas as pd
    import matplotlib
    import matplotlib.pyplot as plt
    import seaborn as sns

    assert isinstance(path_to_dataset, str)

    order_file_path = path_to_dataset + '/orders.csv'
    order_product_prior_file_path = path_to_dataset + '/order_products__prior.csv'

    orders = pd.read_csv(order_file_path)
    order_products_prior = pd.read_csv(order_product_prior_file_path)

    order_id_count_products = order_products_prior.groupby(by='order_id').count()
    orders_with_count = order_id_count_products.merge(orders, on='order_id')
    order_by_date = orders.groupby(by='days_since_prior_order').count()
    # take above table and group by days_since_prior_order

    df_mean_order_size = orders_with_count.groupby(by='days_since_prior_order').mean()['product_id']
    df_mean_order_renamed = df_mean_order_size.rename('average_order_size')

    bubble_plot_dataframe = pd.concat([order_by_date['order_id'], df_mean_order_renamed], axis=1)

    bubble_plot_dataframe['average_order_size'].index.to_numpy()

    fig = plt.figure(figsize=[15,7.5])
    ax = fig.add_subplot()
    plt.scatter(bubble_plot_dataframe['average_order_size'].index.to_numpy(), bubble_plot_dataframe['order_id'].values, s=((bubble_plot_dataframe['average_order_size'].values/bubble_plot_dataframe['average_order_size'].values.mean())*10)**3.1, alpha=0.5, c = '0.5')

    plt.xticks(np.arange(0, 31, 1.0));
    ax.xaxis.grid(True)
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.set_xlabel('Days since previous order', fontsize=16)
    ax.set_ylabel('Number of orders / 1000', fontsize=16)
    ax.get_xaxis().set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x))))
    ax.get_yaxis().set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x/1000))))
    my_yticks = ax.get_yticks()
    plt.yticks([my_yticks[-2], my_yticks[0]], visible=True);

    fig = plt.figure(figsize=[10,9])
    ax = fig.add_subplot()
    plt.scatter(bubble_plot_dataframe['average_order_size'].index.to_numpy()[:8], bubble_plot_dataframe['order_id'].values[:8], s=((bubble_plot_dataframe['average_order_size'].values[:8]/bubble_plot_dataframe['average_order_size'].values.mean())*10)**3.1, alpha=0.5, c = '0.5')

    plt.xticks(np.arange(0, 8, 1.0));
    ax.xaxis.grid(True)
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.set_xlabel('Days since previous order', fontsize=16)
    ax.set_ylabel('Number of orders / 1000', fontsize=16)
    ax.get_xaxis().set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x))))
    ax.get_yaxis().set_major_formatter(matplotlib.ticker.FuncFormatter(lambda x, p: format(int(x/1000))))
    my_yticks = ax.get_yticks()
    plt.yticks([my_yticks[-2], my_yticks[0]], visible=True);

def orderTimeHeatMaps(path_to_dataset):
    """
    Plots the distribution of order with respect to hour of day and day of the week.
    :param path_to_dataset: this path should have all the .csv files for the dataset
    :type path_to_dataset: str
    """

    assert isinstance(path_to_dataset, str)

    import pandas as pd
    import matplotlib.pyplot as plt
    import seaborn as sns
    import numpy as np

    order_file_path = path_to_dataset + '/orders.csv'

    orders = pd.read_csv(order_file_path)

    grouped_data = orders.groupby(["order_dow", "order_hour_of_day"])["order_number"].aggregate("count").reset_index()
    grouped_data = grouped_data.pivot('order_dow', 'order_hour_of_day', 'order_number')

    grouped_data.index = pd.CategoricalIndex(grouped_data.index, categories=[0,1,2,3,4,5,6])
    grouped_data.sort_index(level=0, inplace=True)

    plt.figure(figsize=(12,6))
    hour_of_day = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14','15','16', '17', '18', '19','20', '21', '22', '23']
    dow = [ 'SUN', 'MON', 'TUES', 'WED', 'THUR','FRI','SAT']

    ax = sns.heatmap(grouped_data, xticklabels=hour_of_day,yticklabels=dow,cbar_kws={'label': 'Number Of Orders Made/1000'})
    cbar = ax.collections[0].colorbar
    cbar.set_ticks([0, 10000, 20000, 30000, 40000, 50000])
    cbar.set_ticklabels(['0','10.0','20.0','30.0','40.0','50.0'])
    ax.figure.axes[-1].yaxis.label.set_size(15)
    ax.figure.axes[0].yaxis.label.set_size(15)
    ax.figure.axes[0].xaxis.label.set_size(15)

    ax.set(xlabel='Hour of Day', ylabel= "Day of the Week")
    ax.set_title("Number of orders made by Day of the Week vs Hour of Day", fontsize=15)
    plt.show()

    grouped_data = orders.groupby(["order_dow", "order_hour_of_day"])["order_number"].aggregate("count").reset_index()
    grouped_data = grouped_data.pivot('order_dow', 'order_hour_of_day', 'order_number')

    grouped_data.index = pd.CategoricalIndex(grouped_data.index, categories=[0,1,2,3,4,5,6])
    grouped_data.sort_index(level=0, inplace=True)

    plt.figure(figsize=(12,6))
    hour_of_day = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14','15','16', '17', '18', '19','20', '21', '22', '23']
    dow = [ 'SUN', 'MON', 'TUES', 'WED', 'THUR','FRI','SAT']

    ax = sns.heatmap(np.log(grouped_data), xticklabels=hour_of_day,yticklabels=dow,cbar=False)
    cbar = ax.collections[0].colorbar

    ax.figure.axes[-1].yaxis.label.set_size(15)
    ax.figure.axes[0].yaxis.label.set_size(15)
    ax.figure.axes[0].xaxis.label.set_size(15)

    ax.set(xlabel='Hour of Day', ylabel= "Day of the Week")
    ax.set_title("Number of orders made by Day of the Week vs Hour of Day (Log Scale)", fontsize=15)
    plt.show()

def generateWordCloud(path_to_dataset):
    """
    Generates word cloud.
    :param path_to_dataset: path to dataset
    :type path_to_dataset: str
    """

    assert isinstance(path_to_dataset, str)

    from wordcloud import WordCloud
    import pandas as pd
    import matplotlib.pyplot as plt

    product_path = path_to_dataset + "/products.csv"
    aisles_path = path_to_dataset + "/aisles.csv"
    departments_path = path_to_dataset + "/departments.csv"
    order_product_prior_path = path_to_dataset + "/order_products__prior.csv"

    df_products = pd.read_csv(product_path)
    df_aisles = pd.read_csv(aisles_path)
    df_departments = pd.read_csv(departments_path)
    df_order_products_prior = pd.read_csv(order_product_prior_path)

    # Merge Prior orders, Product, Aisle and Department
    df_order_products_prior_merged = pd.merge(
                                        pd.merge(pd.merge(df_order_products_prior, df_products, on="product_id", how="left"),
                                            df_aisles,
                                            on="aisle_id",
                                            how="left"),
                                        df_departments,
                                        on="department_id",
                                        how="left")
    # Top N products by frequency
    top_products = df_order_products_prior_merged["product_name"].value_counts()

    d = top_products.to_dict()

    wordcloud = WordCloud(background_color='white')
    wordcloud.generate_from_frequencies(frequencies=d)
    plt.figure(figsize = (8,8))
    plt.imshow(wordcloud, interpolation="bilinear")
    plt.axis("off")
    plt.show()

def no_of_orders(path_to_data = './instacart-market-basket-analysis'):
    """
    pass path to orders.csv
    """

    bins = 10
    path = path_to_data + '/orders.csv'
    import numpy as np # linear algebra
    import matplotlib.pyplot as plt
    import seaborn as sns
    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.mlab as mlab
    import seaborn as sns
    from scipy.optimize import curve_fit
    from IPython.display import display, HTML

    orders = pd.read_csv(path)
    sns.set_style('dark')
    customer_no = orders.groupby("user_id", as_index = False)["order_number"].max()

    n, bins, patches = plt.hist(customer_no["order_number"] , bins, color='blue', alpha=0.5)

    plt.xlabel("No. of Orders")
    plt.ylabel("Count")
    plt.title("Number of Orders per Customer")

def freq_product(path1 = "./instacart-market-basket-analysis/order_products__train.csv",path2 = "./instacart-market-basket-analysis/order_products__prior.csv" , path3 = "./instacart-market-basket-analysis/products.csv"):
    import numpy as np # linear algebra
    import matplotlib.pyplot as plt
    import seaborn as sns
    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.mlab as mlab
    import seaborn as sns
    from scipy.optimize import curve_fit
    from IPython.display import display, HTML
    order_products_train = pd.read_csv(path1)
    order_products_prior = pd.read_csv(path2)
    products = pd.read_csv(path3)
    t_p = order_products_train.append(order_products_prior,ignore_index = True)
    prod = t_p.groupby("product_id",as_index = False)["order_id"].count()

    top = 20
    product_Count = prod.sort_values("order_id",ascending = False)
    df1 = product_Count.iloc[0:top,:]
    df1 = df1.merge(products,on = "product_id")
    display(df1.loc[:,["product_name"]])

def dept_prod(m = "./instacart-market-basket-analysis/products.csv" , n = "./instacart-market-basket-analysis/departments.csv" , p = "./instacart-market-basket-analysis/aisles.csv"):
    import numpy as np # linear algebra
    import matplotlib.pyplot as plt
    import seaborn as sns
    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.mlab as mlab
    import seaborn as sns
    from scipy.optimize import curve_fit
    from IPython.display import display, HTML
    products = pd.read_csv(m)
    departments = pd.read_csv(n)
    aisles = pd.read_csv(p)
    x = pd.merge(left=products, right=departments, how='left')
    lists = pd.merge(left = x, right=aisles, how='left')

    group_list = lists.groupby("department")["product_id"].aggregate({'Total_products': 'count'})
    final = group_list.reset_index()
    final.sort_values(by='Total_products', ascending=False, inplace=True)

    sns.set_style('white')
    ax = sns.barplot(x="Total_products", y="department", data=final,color = 'gray' )

    r = ax.spines["right"].set_visible(False)
    t = ax.spines["top"].set_visible(False)

def dept_reorder(path = "order_products__prior.csv" , m = "products.csv" , n = "departments.csv" , p = "aisles.csv"):
    import numpy as np # linear algebra
    import matplotlib.pyplot as plt
    import seaborn as sns
    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.mlab as mlab
    import seaborn as sns
    from scipy.optimize import curve_fit
    from IPython.display import display, HTML
    products = pd.read_csv(m)
    departments = pd.read_csv(n)
    aisles = pd.read_csv(p)

    order_products_prior = pd.read_csv(path)

    order_products_prior = pd.merge(order_products_prior, products, on='product_id', how='left')
    order_products_prior = pd.merge(order_products_prior, aisles, on='aisle_id', how='left')
    order_products_prior = pd.merge(order_products_prior, departments, on='department_id', how='left')

    df2 = order_products_prior.groupby(["department"])["reordered"].aggregate("mean").reset_index()

    plt.figure(figsize=(12,8))
    sns.set_style('white')

    ax1 = sns.scatterplot(df2['reordered'].values,df2['department'].values , color = 'gray')
    plt.ylabel('Department', fontsize=15)
    plt.xlabel('Reorder Ratio' , fontsize=15)
    plt.title("Department wise reorder ratio", fontsize=15)
    plt.xticks(rotation='horizontal')
    r = ax1.spines["right"].set_visible(False)
    t = ax1.spines["top"].set_visible(False)
    plt.show()


import datetime as dt
import time
import uuid

import pytest

import timtools.settings
from timtools.notify.notify import AbstractNotify

timtools.settings.replace_config_with_dummy()

class Notify(AbstractNotify):
    config_key = "test"

    def send_text(self, *args, **kwargs):
        ...

    def send_file(self, *args, **kwargs):
        ...

    def send_image(self, *args, **kwargs):
        ...

def test_no_config():
    if Notify.config_key in timtools.settings.USER_CONFIG:
        del timtools.settings.USER_CONFIG[Notify.config_key]

    with pytest.raises(ValueError):
        _ = Notify().config

def test_single_instance_timeout():
    Notify.timeout_window = dt.timedelta(milliseconds=500)
    notification_msg = f"TEST -- {uuid.uuid4()}"

    t = Notify()
    t._log_notification(notification_msg)
    assert t._is_timedout(notification_msg) is True
    time.sleep(t.timeout_window.total_seconds())
    assert t._is_timedout(notification_msg) is False

def test_cross_instance_timeout():
    Notify.timeout_window = dt.timedelta(milliseconds=500)
    notification_msg = f"TEST -- {uuid.uuid4()}"

    t = Notify()
    t._log_notification(notification_msg)

    t2 = Notify()
    assert t2._is_timedout(notification_msg) is True

    time.sleep(t.timeout_window.total_seconds())

    t3 = Notify()
    assert t3._is_timedout(notification_msg) is False


from enum import Enum
from io import TextIOWrapper
from typing import Any, Dict
import requests
import config

from models import GoodDetail, ReceiptInfo, ReceiptMetadata, ReceiptResult

class StatusCodes(Enum):
    SUCCESS = 1
    TOO_MANY_REQUESTS = 3

def request_receipt_details(qr_file_data: TextIOWrapper) -> ReceiptResult:
    url = 'https://proverkacheka.com/api/v1/check/get'
    data = {'token': config.PROVERKA_CHECKA_TOKEN}
    files = {'qrfile': qr_file_data}
    response = requests.post(
        url, data=data, files=files)  # send request to API
    parsed_data = response.json()
    list_of_items = []
    if (response.status_code == 200):
        if (parsed_data["code"] != StatusCodes.SUCCESS.value):
            return ReceiptResult(is_ok=False, errror_msg=str(parsed_data["data"]))

        receipt_info = parsed_data["data"]['json']
        metadata = get_metadata(receipt_info)

        for k in receipt_info['items']:
            unit_price = round(k['price']/100) if is_countable(k) else to_rub_per_kg(k['price'], k['quantity'])
            list_of_items.append(GoodDetail(
                label=k['name'], unit_price=unit_price, count=k['quantity'], sum_price=k['price']/100))
        return ReceiptResult(ReceiptInfo(goods=list_of_items, metadata=metadata))
    else:
        return ReceiptResult(is_ok=False, errror_msg="Response status code is " + response.status_code)

def get_metadata(receipt_info: Dict[str, Any]) -> ReceiptMetadata:
    return ReceiptMetadata(
        receipt_id=receipt_info.get("metadata", {}).get("id", -1),
        retail_place=receipt_info.get("retailPlace", ""),
        total_sum=receipt_info.get("totalSum", 0)/100,
        date_time=receipt_info.get("dateTime", "")
    )

def is_countable(item):
    return isinstance(item['quantity'], int)

def to_rub_per_kg(total_price: float, quantity: float) -> int:
    return round(float('{:.2f}'.format(total_price / 100 * quantity)))


from unittest.mock import Mock

import pytest

from libpythonproo import github_api

@pytest.fixture
def avatar_url(mocker):
    resp_mock = Mock()
    url = 'https://avatars.githubusercontent.com/u/94086373?v=4'
    resp_mock.json.return_value = {
        'login': 'gustavossandrin', 'id': 94086373, 'node_id': 'U_kgDOBZuk5Q',
        'avatar_url': url
    }
    get_mock = mocker.patch('libpythonproo.github_api.requests.get')
    get_mock.return_value = resp_mock
    return url

def teste_buscar_avatar(avatar_url):
    url = github_api.buscar_avatar('gustavossandrin')
    assert avatar_url == url

def teste_buscar_avatar_intregracao():
    url = github_api.buscar_avatar('gustavossandrin')
    assert 'https://avatars.githubusercontent.com/u/94086373?v=4' == url


import telebot
from telebot import types
import os
import django
from slugify import slugify

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'news.settings')
django.setup()

from social_django.models import UserSocialAuth
from main.models import News
from main.models import Category

class Post:
    def __init__(self, user_id=None, title=None, category=None, text=None, description=None, image=None):
        self.user_id = user_id
        self.title = title
        self.category = category
        self.text = text
        self.description = description
        self.image = image

    def publish_post(self):
        self.slug = slugify(self.title)
        category = Category.objects.get(name=self.category)
        news = News(title=self.title, text=self.text, category=category, description=self.description, image=self.image, slug=self.slug)
        news.save()

API_TOKEN = '6478915421:AAHZH_Zxp49blHcsl7bRga0WaxOQotNn-V4'

bot = telebot.TeleBot(API_TOKEN)

def send_news_details(news_details):
    bot.send_message('-4004087466', f"Опубликована новая новость\n{news_details['title']}\n{news_details['description']}\n{news_details['category']}")

# def send_news_details(news_details):
#     bot.send_photo('-4004087466', news_details['image'], f'''Опубликована новая новость\n{news_details['title']}\n{news_details['description']}\n{news_details['category']}''')

@bot.message_handler(commands=['start'])
def login_keyboard(message):
    markup = types.ReplyKeyboardMarkup(resize_keyboard=True)
    button1 = types.KeyboardButton("Войти в аккаунт")
    markup.add(button1)
    bot.reply_to(message, "Привет!\nЯ бот который умеет взаимодействовать с новостным сайтом\nВыбери действие на клавиатуре", reply_markup=markup)

@bot.message_handler(func=lambda message: message.text=='Войти в аккаунт')
def main_keyboard(message):
    markup = types.ReplyKeyboardMarkup(resize_keyboard=True)
    buttons = [types.KeyboardButton("Мой профиль"),
                types.KeyboardButton("Создать новость"),
                types.KeyboardButton("Подписаться на рассылку")]
    markup.add(*buttons)
    bot.reply_to(message, "Главное меню. Выберите действие на клавиатуре", reply_markup=markup)

@bot.message_handler(func=lambda message: message.text=='Мой профиль')
def profile_keyboard(message):
    user_id = message.chat.id
    user = UserSocialAuth.objects.get(provider='telegram', uid=user_id).user
    bot.send_message(message.chat.id,
                     f"Профиль\n{user.first_name} {user.last_name}\n{user.username}\nПочта: {user.email}\nДата регистрации: {user.date_joined}\nПоследний онлайн: {user.last_login}\nОставлено комментариев: {len(user.profile.get_user_comments())}\nОпубликовано новостей: {len(user.profile.get_user_news())}")

@bot.message_handler(func=lambda message: message.text=='Создать новость')
def create_post_keyboard(message):
    global post
    global create_post_markup
    post = Post(user_id=message.chat.id)
    create_post_markup = types.ReplyKeyboardMarkup(resize_keyboard=True, row_width=3)
    buttons = [types.KeyboardButton("Заголовок"),
                types.KeyboardButton("Категория"),
                types.KeyboardButton("Краткое описание"),
                types.KeyboardButton("Текст"),
                types.KeyboardButton("Изображение"),
                types.KeyboardButton("Просмотр"),
                types.KeyboardButton("Отправить"),
                types.KeyboardButton("На главную")]
    create_post_markup.add(*buttons)
    bot.send_message(message.chat.id, 'Создание новости', reply_markup=create_post_markup)

@bot.message_handler(func=lambda message: message.text=='Заголовок')
def title(message):
    title_msg = bot.send_message(message.chat.id, 'Введите заголовок новости')
    bot.register_next_step_handler(title_msg, title_validation)

@bot.message_handler(func=lambda message: message.text=='Краткое описание')
def description(message):
    title = bot.send_message(message.chat.id, 'Введите описание новости')
    bot.register_next_step_handler(title, description_validation)

@bot.message_handler(func=lambda message: message.text=='Текст')
def text(message):
    title = bot.send_message(message.chat.id, 'Введите текст новости')
    bot.register_next_step_handler(title, text_validation)

@bot.message_handler(func=lambda message: message.text=='Категория')
def category(message):
    markup = types.ReplyKeyboardMarkup(resize_keyboard=True, row_width=3)
    categories = Category.objects.all()
    buttons = []
    for category in categories:
        buttons.append(types.KeyboardButton(category.name))
    markup.add(*buttons)
    category = bot.send_message(message.chat.id, 'Выберите категорию', reply_markup=markup)
    bot.register_next_step_handler(category, category_selection)

@bot.message_handler(func=lambda message: message.text=='Изображение')
def image(message):
    title = bot.send_message(message.chat.id, 'Выберите изображение')
    bot.register_next_step_handler(title, image_validation)

@bot.message_handler(func=lambda message: message.text=='Отправить')
def send_post(message):
    global post
    if post.title and post.description and post.image and post.text:
        post.publish_post()
        news = News.objects.get(title=post.title)
        bot.send_message(message.chat.id, f'Пост опубликован\nссылка на пост: 127.0.0.1:8000{news.get_absolute_url()}')
    else:
        bot.send_message(message.chat.id, 'Не все поля заполнены!')

@bot.message_handler(func=lambda message: message.text=='Просмотр')
def view_post(message):
    bot.send_message(message.chat.id, f'Заголовок: {post.title}\nкатегория: {post.category}\nописание: {post.description}\nтекст: {post.text}')

@bot.message_handler(func=lambda message: message.text=='На главную')
def to_main_keyboard(message):
    main_keyboard(message)

def category_selection(message):
    global post
    global create_post_markup
    post.category = message.text
    bot.send_message(message.chat.id, 'Категория выбрана', reply_markup=create_post_markup)

def text_validation(message):
    global post
    global create_post_markup
    if len(message.text) <= 300:
        text = message.text
        bot.send_message(message.chat.id, 'Текст заполнен', reply_markup=create_post_markup)
    else:
        text = None
        bot.send_message(message.chat.id, 'Длина текста не может быть более 300 символов!', reply_markup=create_post_markup)
    post.text = text

def title_validation(message):
    global post
    global create_post_markup
    if len(message.text) <= 50:
        title = message.text
        bot.send_message(message.chat.id, 'Заголовок заполнен', reply_markup=create_post_markup)
    else:
        title = None
        bot.send_message(message.chat.id, 'Длина заголовка не может быть более 50 символов!', reply_markup=create_post_markup)
    post.title = title

def description_validation(message):
    global post
    global create_post_markup
    if len(message.text) <= 100:
        description = message.text
        bot.send_message(message.chat.id, 'Описание заполнено', reply_markup=create_post_markup)
    else:
        description = None
        bot.send_message(message.chat.id, 'Длина описания не может быть более 100 символов!', reply_markup=create_post_markup)
    post.description = description

def image_validation(message):
    global create_post_markup
    global post
    post.image = message.text
    bot.send_message(message.chat.id, 'Изображение выбрано', reply_markup=create_post_markup)

@bot.message_handler(func=lambda message: message.text=='Подписаться на рассылку')
def subscription_keyboard(message):
    buttons = [[types.InlineKeyboardButton(category.name, callback_data=category.name, url=f'https://t.me/django_news_subscribe_bot?start={category.slug}') for category in Category.objects.all()]]
    subscription_markup = types.InlineKeyboardMarkup(buttons, row_width=4)
    bot.reply_to(message, "Выберите ниже желаемые категории", reply_markup=subscription_markup)

# @bot.message_handler(func=lambda message: message.text=='Подписаться на рассылку')
# def subscription_keyboard(message):
#     global subscription_markup
#     buttons = [[types.InlineKeyboardButton("Спорт", callback_data='Спорт'),
#                 types.InlineKeyboardButton("Политика", callback_data='Политика'),
#                 types.InlineKeyboardButton("Кино", callback_data='Кино'),
#                 types.InlineKeyboardButton("Бизнес", callback_data='Бизнес')],
#                 [types.InlineKeyboardButton("Подписаться на рассылку", callback_data='Подписка', url='https://t.me/django_news_subscribe_bot')]]
#     subscription_markup = types.InlineKeyboardMarkup(buttons, row_width=4)
#     bot.reply_to(message, "Выберите ниже желаемые категории", reply_markup=subscription_markup)

# @bot.callback_query_handler(func=lambda call: True)
# def inline_callback(call):
#     if call.message:
#         bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id, text=f'{call.message.text}\n{call.data} ✅', reply_markup=subscription_markup)

if __name__ == '__main__':
    bot.polling()


import datetime
import sys

now = datetime.datetime.now()
today = now.strftime('%Y-%m-%d')
timestamp = now.strftime('%Y%m%d %H:%M:%S')
short_title = sys.argv[1] if len(sys.argv) > 1 else 'post'
path = '_posts/%s-%s.md' % (today, short_title)

print(f"path: {path}")

header = """
---
layout: post
title:  "%s"
date:  %s +0800
categories: default
tags:
 - blogging
---
""" % (short_title, timestamp)

with open(path, "w+") as f:
    f.write(header)

if len(sys.argv) == 1:
    print('***WARN: default title is used***')


import pickle
import time
import argparse
import os
import errno
import numpy as np

from SAC import trainSAC
from SACHyperparameters import Hyperparameters

def my_import(name):
    components = name.split('/')
    mod = __import__(components[0])
    for comp in components[1:]:
        mod = getattr(mod, comp)
    return mod

def parseArguments():
    """
    Parse arguments from the command line.

    Returns
    -------
    root_dir : str
        Root directory for saving the results.

    hp : Hyperparameters
        Hyperparameters for the SAC algorithm.

    """
    # Parse arguments
    parser = argparse.ArgumentParser(description='MLQTransfer')
    parser.add_argument('-r', '--root_dir', type=str, required=True, help='Root directory for saving the results')
    parser.add_argument('-hp', '--hyperparameters', type=str, help='File containing the hiperparameters')
    parser.add_argument('-shp', '--save_hyperparameters', action='store_true', help='Save the hyperparameters')
    args = parser.parse_args()

    if args.hyperparameters is None:
        hp = Hyperparameters(root_dir=args.root_dir)
    else:
        print("---------------------------------------")
        print("Loading hyperparameters from: ", args.hyperparameters)
        print("---------------------------------------")
        hp = my_import(args.hyperparameters).Hyperparameters(root_dir=args.root_dir)

    root_dir = args.root_dir
    saveHyperparameters = args.save_hyperparameters

    if saveHyperparameters:
        print("Saving hyperparameters")
        filepath = root_dir + "/hyperparameters_" + time.strftime("%Y%m%d-%H%M%S") + ".pkl"
        try:
            os.makedirs(root_dir)
        except OSError as exc:
            if exc.errno == errno.EEXIST and os.path.isdir(root_dir):
                pass
            else: raise

        with open(filepath, 'wb') as f:
            pickle.dump(hp, f)

    return root_dir, hp

if __name__ == '__main__':
    # Parse arguments
    root_dir, hp = parseArguments()

    # Create and Train the agent
    trainSAC(
        env_collect_py=hp.env_collect_py,
        env_eval_py=hp.env_eval_py,
        root_dir=root_dir,
        num_iterations=hp.num_iterations,
        actor_fc_layers=hp.actor_fc_layers,
        critic_joint_fc_layers=hp.critic_joint_fc_layers,
        replay_buffer_capacity=hp.replay_buffer_capacity,
        initial_collect_steps=hp.initial_collect_steps,
        eval_interval=hp.eval_interval,
        summary_interval=hp.summary_interval,
        collect_steps_per_iteration=hp.collect_steps_per_iteration,
        batch_size=hp.batch_size,
        actor_learning_rate=hp.actor_learning_rate,
        critic_learning_rate=hp.critic_learning_rate,
        alpha_learning_rate=hp.alpha_learning_rate,
        gamma=hp.gamma,
        num_eval_episodes=hp.num_eval_episodes,
        target_entropy=hp.target_entropy,
        train_checkpoint_interval=hp.train_checkpoint_interval,
        policy_checkpoint_interval=hp.policy_checkpoint_interval,
        rb_checkpoint_interval=hp.rb_checkpoint_interval
        )

    max_target_population = np.max(hp.env_eval_py.best_populations[:, :-1][-1, :])
    max_intermediate_population = np.max(hp.env_eval_py.best_populations[:, :-1][1:-1, :])

    print("---------------------------------------")
    print("Training finished")
    print("---------------------------------------")
    print("Best Reward: ", hp.env_eval_py.best_reward)
    print("Final Target Population: ", hp.env_eval_py.best_populations[:, :-1][-1, -1])
    print("Max Target Population: ", max_target_population)
    print("Max intermidiate population: ", max_intermediate_population)
    print("---------------------------------------")


from odoo import api, fields, models, _
from odoo.exceptions import ValidationError
import logging
import time

_logger = logging.getLogger(__name__)
DF = "%Y-%m-%d"
EPS = 0.00001

class Posting(models.Model):
    _inherit = "wc.posting"

    #over write close_date operation for fixing f540 issues
    #this was kind of bug , so overwrite the method by the method below.
    #the source code was copied , and modified part of it.
    @api.multi
    def close_date(self):
        start = time.time()
        _logger.debug("***#close_date: start")

        first = True
        for rec in self:
            rec.add_details()
            rec.state = 'closed'

            if first:
                first = False

                #delete all draft transactions
                #account transactions
                trans = self.env['wc.account.transaction'].sudo().search([
                    ('state','=','draft'),
                    ('company_id','=',self.env.user.company_id.id)
                ])
                _logger.debug("*DRAFT trans: %s", trans)
                if trans:
                    #f540 fix
                    #trans.unlink()
                    raise ValidationError(_("Draft record is remaining in %s! Please confirm or delete it before closing.") % ('account transactions '))

                coll_lines = self.env['wc.collection.line'].sudo().search([
                    ('state','=','draft'),
                    ('company_id','=',self.env.user.company_id.id)
                ])
                _logger.debug("*DRAFT coll lines: %s", coll_lines)
                if coll_lines:
                    #f540 fix
                    #coll_lines.unlink()
                    raise ValidationError(_("Draft record is remaining in %s! Please confirm or delete it before closing.") % ('collection line '))

                collection = self.env['wc.collection'].sudo().search([
                    ('state','=','draft'),
                    ('company_id','=',self.env.user.company_id.id)
                ])
                _logger.debug("*DRAFT collection: %s", collection)
                if collection:
                    #f540 fix
                    #for coll in collection:
                    #    coll.loan_id = False
                    #    coll.loan_payment_id = False
                    #collection.unlink()
                    raise ValidationError(_("Draft record is remaining in %s! Please confirm or delete it before closing.") % ('collection '))

                pay = self.env['wc.loan.payment'].sudo().search([
                    ('state','=','draft'),
                    ('company_id','=',self.env.user.company_id.id)
                ])
                _logger.debug("*DRAFT loan payment: %s", pay)
                if pay:
                    #f540 fix
                    #for p in pay:
                    #    p.collection_id = False
                    #pay.unlink()
                    raise ValidationError(_("Draft record is remaining in %s! Please confirm or delete it before closing.") % ('payment transactions '))

        _logger.debug("***#close_date: stop elapsed=%s", time.time() - start)


#!/usr/bin/env python3
import requests
import json
from bs4 import BeautifulSoup
import os
import socket
from time import sleep
import sys

def wait_till_online():
    try:
        host = socket.gethostbyname("tagesschau.de")
    except:
        sleep(1)
        print("offline")
        wait_till_online()

def get_latest(links):
    return  sorted(links)[-1]

def scrape_links(url):
    page = requests.get(url)
    soup = BeautifulSoup(page.content, 'html.parser')
    # players = soup.find_all('div',  {"class": "ts-mediaplayer ts-mediaplayer--einszueins ts-mediaplayer--list"})

    players = soup.find_all('div',  {"class": "ts-mediaplayer"})
    links = []
    for player_item in players:
        attribs = player_item.attrs
        data = attribs["data-config"]
        try:
            title = json.loads(data)["mc"]["_title"]
            if "tsde" in title or title == "Ganze Sendung":
                if "Gebärdensprache" not in data:
                    links.append(json.loads(data)["mc"]['_mediaArray'][0]["_mediaStreamArray"][4]["_stream"])
        except KeyError:
            pass
    return links

player = "castnow"
if len(sys.argv) > 1:
    player = sys.argv[1]
url = "https://www.tagesschau.de/multimedia/"
wait_till_online()
links = scrape_links(url)
url = get_latest(links)
cmd = f"{player} {url}"
os.system(cmd)


#Size of the points reduced on purpose to run faster

#Important modules
import csv
from plotly.graph_objs import Scattergeo, Layout
from plotly import offline
from datetime import datetime

#Explore the structure of the data
filename = "data/world_fires_7_day.csv"

with open(filename) as f:
	reader = csv.reader(f)
	header_row = next(reader)
	print(header_row)

	#Extracting fire information
	brightness, lons, lats, daynight, date = [], [], [], [], []

	#Look for the relevant information
	lat_index = header_row.index("latitude")
	lon_index = header_row.index("longitude")
	bright_index = header_row.index("bright_ti4")
	dn_index = header_row.index("daynight")
	day_index = header_row.index("acq_date")

	for row in reader:

		try:
			bright = float(row[bright_index])
			lat = float(row[lat_index])
			lon = float(row[lon_index])
			dn = row[dn_index]
			day = datetime.strptime(row[day_index], "%Y-%m-%d")
		except:
			print(f"N/A")
		else:
			lats.append(lat)
			lons.append(lon)
			brightness.append(bright)
			daynight.append(dn)
			date.append(day.date())

data = [{
		'type': 'scattergeo',
		"lon":lons,
		"lat": lats,
		"text": daynight,
		"marker": {
			"size":[brightn/100 for brightn in brightness],
			"color": [brightn/100 for brightn in brightness],
			"colorscale": "Hot",
			"reversescale": True,
			"colorbar": {"title": "Brightness/100"},
			},
		}]

my_layout = Layout(title= "Global Fires 2018")

fig = {"data": data, "layout": my_layout}
offline.plot(fig, filename = "global_fires.html")

f.close()


import torch
import torch.nn.functional as F
import torch.nn as nn
import numpy as np

class BinaryDiceLoss(nn.Module):
    def __init__(self, smooth=1, p=2, reduction='mean'):
        super(BinaryDiceLoss, self).__init__()
        self.smooth = smooth
        self.p = p
        self.reduction = reduction

    def forward(self, predict, target):
        assert predict.shape[0] == target.shape[0], "predict & target batch size don't match"
        predict = predict.contiguous().view(predict.shape[0], -1)
        target = target.contiguous().view(target.shape[0], -1)

        num = torch.sum(torch.mul(predict, target), dim=1)
        den = torch.sum(predict, dim=1) + torch.sum(target, dim=1) + self.smooth

        dice_score = 2*num / den
        loss_avg = 1 - dice_score.mean()

        return loss_avg

class DiceLoss4BraTS(nn.Module):
    def __init__(self, weight=None, ignore_index=None, **kwargs):
        super(DiceLoss4BraTS, self).__init__()
        self.kwargs = kwargs
        self.weight = weight
        self.ignore_index = ignore_index

    def forward(self, predict, target):
        assert predict.shape == target.shape, 'predict %s & target %s shape do not match' % (predict.shape, target.shape)
        dice = BinaryDiceLoss(**self.kwargs)
        total_loss = 0
        predict = F.sigmoid(predict)

        for i in range(target.shape[1]):
            if i != self.ignore_index:
                dice_loss = dice(predict[:, i], target[:, i])
                if self.weight is not None:
                    assert self.weight.shape[0] == target.shape[1], \
                        'Expect weight shape [{}], get[{}]'.format(target.shape[1], self.weight.shape[0])
                    dice_loss *= self.weights[i]
                total_loss += dice_loss

        return total_loss/(target.shape[1]-1 if self.ignore_index!=None else target.shape[1])

class BCELoss4BraTS(nn.Module):
    def __init__(self, ignore_index=None, **kwargs):
        super(BCELoss4BraTS, self).__init__()
        self.kwargs = kwargs
        self.ignore_index = ignore_index
        self.criterion = nn.BCEWithLogitsLoss()

    def weighted_BCE_cross_entropy(self, output, target, weights = None):
        if weights is not None:
            assert len(weights) == 2
            output = torch.clamp(output, min=1e-7, max=1-1e-7)
            bce = weights[1] * (target * torch.log(output)) + \
                  weights[0] * ((1-target) * torch.log((1-output)))
        else:
            output = torch.clamp(output, min=1e-3, max=1 - 1e-3)
            bce = target * torch.log(output) + (1-target) * torch.log((1-output))
        return torch.neg(torch.mean(bce))

    def forward(self, predict, target):
        assert predict.shape == target.shape, 'predict & target shape do not match'
        total_loss = 0
        for i in range(target.shape[1]):
            if i != self.ignore_index:
                bce_loss = self.criterion(predict[:, i], target[:, i])
                total_loss += bce_loss

        return total_loss.mean()

class BCELossBoud(nn.Module):
    def __init__(self, weight=None, ignore_index=None, **kwargs):
        super(BCELossBoud, self).__init__()
        self.kwargs = kwargs
        self.weight = weight
        self.ignore_index = ignore_index
        self.criterion = nn.BCEWithLogitsLoss()

    def weighted_BCE_cross_entropy(self, output, target, weights = None):
        if weights is not None:
            assert len(weights) == 2
            output = torch.clamp(output, min=1e-3, max=1-1e-3)
            bce = weights[1] * (target * torch.log(output)) + \
                  weights[0] * ((1-target) * torch.log((1-output)))
        else:
            output = torch.clamp(output, min=1e-3, max=1 - 1e-3)
            bce = target * torch.log(output) + (1-target) * torch.log((1-output))
        return torch.neg(torch.mean(bce))

    def forward(self, predict, target):

        bs, category, depth, width, heigt = target.shape
        bce_loss = []
        for i in range(predict.shape[1]):
            pred_i = predict[:,i]
            targ_i = target[:,i]
            tt = np.log(depth * width * heigt / (target[:, i].cpu().data.numpy().sum()+1))
            bce_i = self.weighted_BCE_cross_entropy(pred_i, targ_i, weights=[1, tt])
            bce_loss.append(bce_i)

        bce_loss = torch.stack(bce_loss)
        total_loss = bce_loss.mean()
        return total_loss


from netCDF4 import Dataset as NetCDFFile

from mpas_tools.planar_hex import make_planar_hex_mesh
from mpas_tools.io import write_netcdf
from mpas_tools.mesh.conversion import convert, cull
from mpas_tools.logging import check_call

from compass.model import make_graph_file
from compass.step import Step

class SetupMesh(Step):
    """
    A step for creating a mesh and initial condition for enthalpy benchmark
    test cases
    """
    def __init__(self, test_case):
        """
        Create the step

        Parameters
        ----------
        test_case : compass.TestCase
            The test case this step belongs to
        """
        super().__init__(test_case=test_case, name='setup_mesh')
        self.add_output_file(filename='graph.info')
        self.add_output_file(filename='landice_grid.nc')

    # no setup() method is needed

    def run(self):
        """
        Run this step of the test case
       """
        logger = self.logger
        section = self.config['enthalpy_benchmark']
        nx = section.getint('nx')
        ny = section.getint('ny')
        dc = section.getfloat('dc')
        levels = section.get('levels')

        dsMesh = make_planar_hex_mesh(nx=nx, ny=ny, dc=dc, nonperiodic_x=True,
                                      nonperiodic_y=True)

        write_netcdf(dsMesh, 'grid.nc')

        dsMesh = cull(dsMesh, logger=logger)
        dsMesh = convert(dsMesh, logger=logger)
        write_netcdf(dsMesh, 'mpas_grid.nc')

        args = ['create_landice_grid_from_generic_MPAS_grid.py',
                '-i', 'mpas_grid.nc',
                '-o', 'landice_grid.nc',
                '-l', levels,
                '--thermal']

        check_call(args, logger)

        make_graph_file(mesh_filename='landice_grid.nc',
                        graph_filename='graph.info')

        _setup_initial_conditions(section, 'landice_grid.nc')

def _setup_initial_conditions(section, filename):
    """ Add the initial conditions for enthalpy benchmark A """
    thickness = section.getfloat('thickness')
    basal_heat_flux = section.getfloat('basal_heat_flux')
    surface_air_temperature = section.getfloat('surface_air_temperature')
    temperature = section.getfloat('temperature')

    with NetCDFFile(filename, 'r+') as gridfile:
        thicknessVar = gridfile.variables['thickness']
        bedTopography = gridfile.variables['bedTopography']
        basalHeatFlux = gridfile.variables['basalHeatFlux']
        surfaceAirTemperature = gridfile.variables['surfaceAirTemperature']
        temperatureVar = gridfile.variables['temperature']

        thicknessVar[:] = thickness
        bedTopography[:] = 0
        basalHeatFlux[:] = basal_heat_flux
        surfaceAirTemperature[:] = surface_air_temperature
        temperatureVar[:] = temperature


import pandas as pd
from pandas import DataFrame as df
import datetime
from datetime import datetime as dt
from single_trial import *

def run_experiment(pid):
  try:
    print('Loading config_{}.csv...'.format(pid), end='\r')
    config = pd.read_csv(
        os.path.join(PATH_INPUT, 'config_{}.csv'.format(pid)),
        keep_default_na=False).to_dict(orient='records')
    print('Loading config_{}.csv...done'.format(pid))

    print('Loading block_parameters_{}.csv...'.format(pid), end='\r')
    block_params = pd.read_csv(
        os.path.join(PATH_INPUT, 'block_parameters_{}.csv'.format(pid)),
        keep_default_na=False).to_dict(orient='records')
    print('Loading block_parameters_{}.csv...done'.format(pid))

    print('Loading experimental_parameters_{}.csv...'.format(pid), end='\r')
    experimental_params = pd.read_csv(
        os.path.join(PATH_INPUT, 'experimental_parameters_{}.csv'.format(pid)),
        keep_default_na=False).to_dict(orient='records')
    print('Loading experimental_parameters_{}.csv...done'.format(pid))
  except BaseException as error:
    exit('\n{}\n{}\n{}\n{}'.format(error,
                                  '#######################',
                                  '### EXITING PROGRAM ###',
                                  '#######################'))
  stims = STIMULI
  try:
    print('Loading calibration_parameters_{}.csv...'.format(pid), end='\r')
    calibration_params = pd.read_csv(
        os.path.join(PATH_INPUT, 'calibration_parameters_{}.csv'.format(pid)),
        keep_default_na=False).to_dict(orient='records')[0]
    print('Loading calibration_parameters_{}.csv...done\n'.format(pid))

    origin_left =  (monitorunittools.pix2deg(calibration_params['x_offset_LE_final'], MONITOR),
                    monitorunittools.pix2deg(calibration_params['y_offset_LE_final'], MONITOR))
    origin_right = (monitorunittools.pix2deg(calibration_params['x_offset_RE_final'], MONITOR),
                    monitorunittools.pix2deg(calibration_params['y_offset_RE_final'], MONITOR))
    stims = init_stimuli(origin_left, origin_right)
  except BaseException as error:
    print('calibration_parameters_{}.csv not found! Using default values.\n'.format(pid))

  os.makedirs(PATH_OUTPUT, exist_ok=True)
  config_out = os.path.join(PATH_OUTPUT, 'out_config_{}.csv'.format(pid))
  block_out = os.path.join(PATH_OUTPUT, 'out_block_parameters_{}.csv'.format(pid))
  exp_out = os.path.join(PATH_OUTPUT, 'out_experimental_parameters_{}.csv'.format(pid))

  config_df = df.from_dict(config)
  config_df.to_csv(config_out, mode='w+', index=False,
                   header=not os.path.exists(config_out))

  iteration = block_number = block_start_time = inter_block_pause_duration = 0
  last_block = block_params[-1]['block']

  show_instructions()
  show_pre_trial_countdown(stims)

  print(origin_left)

  for exp_param in experimental_params:
    iteration += 1
    trial = Trial(stims, exp_param, iteration)

    if trial.block > block_number:
      if not block_number == 0:
        block_end_time = dt.now().strftime('%Y-%m-%d %H:%M:%S.%f')
        block_params[block_number-1]['end_time'] = block_end_time
        block_df = df.from_dict(block_params)
        block_df.to_csv(block_out, mode='w+', index=False,
                        header=not os.path.exists(block_out))
        print('### BLOCK {} END: {}'.format(block_number, block_end_time))
        show_inter_block_countdown(inter_block_pause_duration)
        show_pre_trial_countdown(stims)

      inter_block_pause_duration = block_params[block_number]['inter_block_pause_duration']
      block_start_time = dt.now().strftime('%Y-%m-%d %H:%M:%S.%f')
      block_params[block_number]['start_time'] = block_start_time
      block_df = df.from_dict(block_params)
      block_df.to_csv(block_out, mode='w+', index=False,
                      header=not os.path.exists(block_out))
      block_number = trial.block
      print('### BLOCK {} BEGIN: {}'.format(block_number, block_start_time))

    response = run_trial(trial)

    if response:
      exp_param['response'] = response[0].name
      exp_param['response_time_ms'] = [response[0].rt * 1000]
    else:
      exp_param['response'] = 'NA'
      exp_param['response_time_ms'] = ['NA']

    exp_df = df.from_dict(exp_param)
    exp_df.to_csv(exp_out, mode='a+', index=False,
                  header=not os.path.exists(exp_out))

  block_end_time = dt.now().strftime('%Y-%m-%d %H:%M:%S.%f')
  block_params[block_number-1]['end_time'] = block_end_time
  block_df = df.from_dict(block_params)
  block_df.to_csv(block_out, mode='w+', index=False,
                  header=not os.path.exists(block_out))
  print('### BLOCK {} END: {}'.format(block_number, block_end_time))

  print('Experiment completed:', block_end_time)
  print('Results written to:', PATH_OUTPUT)

  show_completion_message()

def show_instructions():
  print('### EXPERIMENT BEGIN: {}'.format(dt.now().strftime('%Y-%m-%d %H:%M:%S.%f')))
  print('AWAITING RESPONSE', end='\r')
  instructions = visual.TextBox2(WINDOW, text=INSTRUCTIONS,
                                 alignment='center', color='black', bold=True,
                                 letterHeight=28, size=[99999, None])
  instructions.draw()
  WINDOW.flip()

  KEYBOARD.clearEvents()
  response = KEYBOARD.waitKeys(keyList=['space'], waitRelease=False)
  print('Response: {} {}'.format(response[0].name, dt.now().strftime('%Y-%m-%d %H:%M:%S.%f')))
  WINDOW.flip()
  core.wait(0.5)

def show_pre_trial_countdown(stims):
  countdown_stim_L = visual.TextStim(WINDOW)
  countdown_stim_R = visual.TextStim(WINDOW)
  countdown_stim_L.bold = countdown_stim_R.bold = True
  countdown_stim_L.colorSpace = countdown_stim_R.colorSpace = 'rgb'
  countdown_stim_L.color = countdown_stim_R.color = 'black'
  countdown_stim_L.units = countdown_stim_R.units = 'deg'
  countdown_stim_L.size = countdown_stim_R.size = R2_SIZE
  countdown_stim_L.pos = [stims['left'][0]['x'], stims['left'][0]['y']]
  countdown_stim_R.pos = [stims['right'][0]['x'], stims['right'][0]['y']]

  for i in range(3, 0, -1):
    print('COUNTDOWN:', datetime.timedelta(0, i), end='\r')
    countdown_stim_L.text = countdown_stim_R.text = '{}...'.format(i)
    countdown_stim_L.draw()
    countdown_stim_R.draw()
    WINDOW.flip()
    core.wait(1)
  print('      BEGIN       ', end='\r')

  countdown_stim_L.text = countdown_stim_R.text = 'BEGIN'
  countdown_stim_L.draw()
  countdown_stim_R.draw()
  WINDOW.flip()
  core.wait(1)

  WINDOW.flip()
  core.wait(1)

def show_inter_block_countdown(secs):
  print('### INTER-BLOCK PAUSE: {} ms'.format(secs))
  pause_message = visual.TextBox2(WINDOW, text='',
                                  alignment='center', color='black', bold=True,
                                  letterHeight=32, size=[99999, None])
  KEYBOARD.clearEvents()

  for i in range(round(secs/1000), -1, -1):
    response = KEYBOARD.getKeys(keyList=['space'], waitRelease=False)
    if response: break

    time_left = datetime.timedelta(0, i)
    print('COUNTDOWN: {}'.format(time_left), end='\r')
    pause_message.text = 'You may now take a short break.\n\nREMAINING TIME: {}\n\nPress [SPACE BAR] to continue now.'.format(time_left)
    pause_message.draw()
    WINDOW.flip()
    core.wait(secs=1, hogCPUperiod=1)
  print()

  WINDOW.flip()
  core.wait(1)

def show_completion_message():
  message = 'Thank you for your time.\n\nThe experiment is now over.\n\nPress [SPACE BAR] to end this session.'
  completion_message = visual.TextBox2(WINDOW, text=message,
                                 alignment='center', color='black', bold=True,
                                 letterHeight=32, size=[99999, None])
  completion_message.draw()
  WINDOW.flip()

  KEYBOARD.clearEvents()
  KEYBOARD.waitKeys(keyList=['space'], waitRelease=False)
  WINDOW.flip()
  core.wait(0.5)


from odoo import models, fields, api, _
from odoo.exceptions import UserError, ValidationError
from datetime import datetime, timedelta

class AccountJournal(models.Model):
    _inherit = 'account.journal'

    type = fields.Selection(selection_add=[('wip', 'WIP')])

class AccountInvoice(models.Model):
    _inherit = "account.invoice"

    @api.one
    @api.depends('invoice_line_ids')
    def _compute_month_id(self):
        analytic_invoice_id = self.invoice_line_ids.mapped('analytic_invoice_id')
        self.month_id = analytic_invoice_id and analytic_invoice_id[0].month_id.id or False

    target_invoice_amount = fields.Monetary(
        'Target Invoice Amount'
    )
    month_id = fields.Many2one(
        'date.range',
        compute='_compute_month_id',
        string="Invoicing Period"
    )
    wip_move_id = fields.Many2one(
        'account.move',
        string='WIP Journal Entry',
        readonly=True,
        index=True,
        ondelete='restrict',
        copy=False
    )

    def compute_target_invoice_amount(self):
        if self.amount_untaxed != self.target_invoice_amount:
            factor = self.target_invoice_amount / self.amount_untaxed
            discount = (1.0 - factor) * 100
            for line in self.invoice_line_ids:
                line.discount = discount

    def reset_target_invoice_amount(self):
        for line in self.invoice_line_ids:
            line.discount = 0.0

    @api.model
    def invoice_line_move_line_get(self):
        """Copy operating_unit_id from invoice line to move lines"""
        res = super(AccountInvoice, self).invoice_line_move_line_get()
        ailo = self.env['account.invoice.line']
        for move_line_dict in res:
            iline = ailo.browse(move_line_dict['invl_id'])
            if iline.user_id:
                move_line_dict['user_id'] = iline.user_id.id
        return res

    @api.model
    def line_get_convert(self, line, part):
        res = super(AccountInvoice, self).line_get_convert(line, part)
        res['user_id'] = line.get('user_id', False)
        return res

    def inv_line_characteristic_hashcode(self, invoice_line):
        """Overridable hashcode generation for invoice lines. Lines having the same hashcode
        will be grouped together if the journal has the 'group line' option. Of course a module
        can add fields to invoice lines that would need to be tested too before merging lines
        or not."""
        res = super(AccountInvoice, self).inv_line_characteristic_hashcode(invoice_line)
        return res + "%s" % (
            invoice_line['user_id']
        )

    @api.multi
    def _get_timesheet_by_group(self):
        self.ensure_one()
        aal_ids = []
        analytic_invoice_ids = self.invoice_line_ids.mapped('analytic_invoice_id')
        for analytic_invoice in analytic_invoice_ids:
            for grp_line in analytic_invoice.user_total_ids:
                aal_ids += grp_line.detail_ids
        userProject = {}
        for aal in aal_ids:
            project_id, user_id = aal.project_id if aal.project_id else aal.task_id.project_id , aal.user_id
            if project_id.correction_charge and project_id.specs_invoice_report:
                if (project_id, user_id) in userProject:
                    userProject[(project_id, user_id)] = userProject[(project_id, user_id)] + [aal]
                else:
                    userProject[(project_id, user_id)] = [aal]
        return userProject

    @api.multi
    def action_invoice_open(self):
        res = super(AccountInvoice, self).action_invoice_open()
        if self.type in ('out_invoice'):
            analytic_invoice_id = self.invoice_line_ids.mapped('analytic_invoice_id')
            if not analytic_invoice_id:
                return res
            # if invoicing period doesn't lie in same month
            period_date = datetime.strptime(analytic_invoice_id.month_id.date_start, "%Y-%m-%d").strftime('%Y-%m')
            cur_date = datetime.now().date().strftime("%Y-%m")
            invoice_date = self.date or self.date_invoice
            inv_date = datetime.strptime(invoice_date, "%Y-%m-%d").strftime('%Y-%m') if invoice_date else cur_date
            if inv_date != period_date and self.move_id:
                self.action_wip_move_create()
        return res

    @api.model
    def get_wip_default_account(self):
        if self.type in ('out_invoice', 'in_refund'):
            return self.journal_id.default_credit_account_id.id
        return self.journal_id.default_debit_account_id.id

    @api.multi
    def action_wip_move_create(self):
        """ Creates invoice related analytics and financial move lines """
        for inv in self:
            wip_journal = self.env.ref('magnus_timesheet.wip_journal')
            if not wip_journal.sequence_id:
                raise UserError(_('Please define sequence on the type WIP journal.'))
            sequence = wip_journal.sequence_id
            if inv.type in ['out_refund', 'in_invoice','in_refund'] or inv.wip_move_id:
                continue
            date_end = inv.month_id.date_end
            new_name = sequence.with_context(ir_sequence_date=date_end).next_by_id()
            if inv.move_id:
                wip_move = inv.move_id.wip_move_create( wip_journal, new_name, inv.account_id.id, inv.number)
            wip_move.post()
            # make the invoice point to that wip move
            inv.wip_move_id = wip_move.id
            #wip reverse posting
            reverse_date = datetime.strptime(wip_move.date, "%Y-%m-%d") + timedelta(days=1)
            line_amt = sum(ml.credit + ml.debit for ml in wip_move.line_ids)
            reconcile = False
            if line_amt > 0:
                reconcile = True
            reverse_wip_move = wip_move.create_reversals(
                date=reverse_date,
                journal=wip_journal,
                move_prefix='WIP Invoicing Reverse',
                line_prefix='WIP Invoicing Reverse',
                reconcile=reconcile
            )
            if len(reverse_wip_move) == 1:
                wip_nxt_seq = sequence.with_context(ir_sequence_date=reverse_wip_move.date).next_by_id()
                reverse_wip_move.write({'name':wip_nxt_seq})

        return True

    @api.multi
    def action_cancel(self):
        res = super(AccountInvoice, self).action_cancel()
        wip_moves = self.env['account.move']
        for inv in self:
            if inv.wip_move_id:
                wip_moves += inv.wip_move_id

        # First, set the invoices as cancelled and detach the move ids
        self.write({'wip_move_id': False})
        if wip_moves:
            # second, invalidate the move(s)
            wip_moves.button_cancel()
            # delete the move this invoice was pointing to
            # Note that the corresponding move_lines and move_reconciles
            # will be automatically deleted too
            wip_moves.unlink()
        return res

class AccountInvoiceLine(models.Model):
    _inherit = "account.invoice.line"

    analytic_invoice_id = fields.Many2one(
        'analytic.invoice',
        string='Invoice Reference',
        ondelete='cascade',
        index=True
    )
    user_id = fields.Many2one(
        'res.users',
        'Timesheet User',
        index = True
    )
    user_task_total_line_id = fields.Many2one(
        'analytic.user.total',
        string='Grouped Analytic line',
        ondelete='cascade',
        index=True
    )

    @api.depends('account_analytic_id', 'user_id', 'invoice_id.operating_unit_id')
    @api.multi
    def _compute_operating_unit(self):
        super(AccountInvoiceLine, self)._compute_operating_unit()
        for line in self.filtered('user_id'):
            line.operating_unit_id = line.user_id._get_operating_unit_id()

    # @api.multi
    # def write(self, vals):
    #     res = super(AccountInvoiceLine, self).write(vals)
    #     self.filtered('analytic_invoice_id').mapped('invoice_id').compute_taxes() #Issue: Vat creation double after invoice date change
    #     return res

    @api.model
    def default_get(self, fields):
        res = super(AccountInvoiceLine, self).default_get(fields)
        ctx = self.env.context.copy()
        if 'default_invoice_id' in ctx:
            invoice_obj = self.env['account.invoice'].browse(ctx['default_invoice_id'])
            analytic_invoice_id = invoice_obj.invoice_line_ids.mapped('analytic_invoice_id')
            if analytic_invoice_id:
                res['analytic_invoice_id'] = analytic_invoice_id.id
        return res

#    @api.onchange('product_id')
#    def _onchange_product_id(self):
#        if self.analytic_invoice_id:
#            self.invoice_id = self.env['account.invoice'].browse(self.analytic_invoice_id.invoice_ids.id)
#        return super(AccountInvoiceLine, self)._onchange_product_id()


from collections import Counter

import aoc

def part1(data: str, *, days_after: int = 0):
    fishes = [int(n) for n in data.strip().split(",")]

    while days_after:
        fishes_now = fishes[:]
        for i, fish in enumerate(fishes_now):
            fish -= 1
            if fish == -1:
                fishes.append(8)
                fishes[i] = 6
            else:
                fishes[i] = fish
        # print(fishes)

        days_after -= 1

    return len(fishes)

def part2(data: str, *, days_after: int = 0):
    """ Optimized?
    """
    fishes = [int(n) for n in data.strip().split(",")]

    counter = Counter(fishes)

    while days_after:
        # how many "maturing" ?
        maturing = counter.pop(0, 0)

        # shift the counters ( 1 -> 0, 2 -> 1, ..., 8 -> 7 )
        counter = {n - 1: counter[n] for n in range(1, 9)}

        # account for the ones that matured
        counter[8] = maturing
        counter[6] += maturing

        days_after -= 1

    return sum(counter.values())

test_input = "3,4,3,1,2"

def test_part1():
    assert 26 == part1(test_input, days_after=18)
    assert 5934 == part1(test_input, days_after=80)

def test_part2():
    assert 26 == part2(test_input, days_after=18)
    assert 5934 == part2(test_input, days_after=80)

if __name__ == '__main__':
    data = aoc.read_input(__file__)
    print("Part1", part1(data, days_after=80))
    print("Part2", part2(data, days_after=256))


import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
#from scipy import fft, arange
import numpy as np
from pylab import figure
import const as c

def to_plot(out_buffers, inp_signal_buff):

    figure(1)
    ax1 = plt.subplot(611)
    ax1.plot(c.t, inp_signal_buff)
    ax1.set_title('Вход приемника (сигнал + помехи)  ' + str("fs = ") +
                  str(c.fs) + " Hz")
    ax1.grid(True)

    ax2 = plt.subplot(612, sharex=ax1)
    ax2.plot(c.t, out_buffers[0])
    ax2.set_title('Сигнал на выходе канального фильтра (400 - 800 Гц)  ' +
                  str("fs = ") + str(c.fs) + " Hz")
    ax2.grid(True)

    ax3 = plt.subplot(613)
    ax3.plot(c.t2, out_buffers[1])
    ax3.plot(c.t2, out_buffers[2])
    ax3.set_title('Сигнал на выходе когерентного детектора  ' + str("fs = ") +
                  str(c.fs2) + " Hz")
    ax3.grid(True)

    ax5 = plt.subplot(614)
    ax5.plot(c.t2, out_buffers[3], label='8Hz')
    ax5.plot(c.t2, out_buffers[4], label='12Hz')
    ax5.set_title('Сигналы на выходах фильтров 8 и 12 Гц ' + str("fs = ") +
                  str(c.fs2) + " Hz")
    ax5.grid(True)
    ax5.legend()

    ax7 = plt.subplot(615)
    ax7.plot(c.t2, out_buffers[5], label='8Hz')
    ax7.plot(c.t2, out_buffers[6], label='12Hz')
    ax7.plot(c.t2, out_buffers[7], label='8Hz')
    ax7.plot(c.t2, out_buffers[8], label='12Hz')
    ax7.set_title('Сигналы на входах\выходах компараторов ' + str("fs = ") +
                  str(c.fs2) + " Hz")
    ax7.grid(True)
    ax7.legend()

    ax11 = plt.subplot(616)
    ax11.plot(c.t2, out_buffers[9], label='уровень сигнал\шум 8 Гц')
    ax11.plot(c.t2, out_buffers[10], label='уровень сигнал\шум 12 Гц')
    plt.ylim(0, 40)
    ax11.set_title('Индикатор сигнал/шум в канале (разницы\
     уровней в каналах 8 и 12 Гц '+ str("fs = ")\
     + str(c.fs2) + " Hz")
    ax11.grid(True)
    ax11.legend()

def plotSpectrum(y):
    """
	Function to plot the time domain and frequency domain signal
	"""
    figure(2)
    plt.ylim(0, 100)
    plt.xlim(0, 2000)
    plt.grid(True)
    #plt.legend()
    plt.magnitude_spectrum(y, Fs=c.fs, scale='dB')
    plt.ylabel('Уровень (dB)')
    plt.xlabel('Частота (Hz)')


from django.shortcuts import redirect, render, get_object_or_404
from django.urls import reverse

from .models import Product, Review
from .forms import ReviewForm

def product_list_view(request):
    template = 'app/product_list.html'
    products = Product.objects.all()

    context = {
        'product_list': products,
    }

    return render(request, template, context)

def product_view(request, pk):
    template = 'app/product_detail.html'
    product = get_object_or_404(Product, id=pk)
    form = ReviewForm
    key_exists = 'reviewed_products' in request.session
    if not key_exists:
        request.session['reviewed_products'] = []
        reviewed_products = []
    else:
        reviewed_products = request.session['reviewed_products']
    if request.method == 'GET':
        if not pk in reviewed_products:
            is_review_exist = 0
        else:
            is_review_exist = 1
    if request.method == 'POST':
        if not pk in reviewed_products:
            text = request.POST.get('text')
            new_review = Review.objects.create(text=text, product=product)
            reviewed_products.append(pk)
            request.session['reviewed_products'] = reviewed_products
            is_review_exist = 0
        else:
            is_review_exist = 1
    all_review = Review.objects.filter(product__id=pk)
    print(request.session['reviewed_products'])
    context = {
        'form': form,
        'product': product,
        'reviews': all_review,
        'is_review_exist': is_review_exist
    }

    return render(request, template, context)


from code.skipgram import SkipGram
from code.utils import get_test_set
from sklearn.decomposition import PCA
import numpy as np
import copy

def evaluate_w2v(w2v, sentences):
    """
    Parameters:
    - w2v (SkipGram): Pre-trained SkipGram
    - sentences (list): Clean evaluation data
    Output:
    - errors (np.array): MAE between predicted similarity and ground-truth
    """
    # Get predictions and labels
    predictions = np.array([simil(w2v, sent) for sent in sentences])
    labels = np.array([float(sent[2]) for sent in sentences])

    # Remove None
    idx = np.where(predictions != None)

    # Predictions and labels
    predictions = predictions[idx]
    labels = labels[idx]

    # Compute mean error
    errors = np.abs(predictions*10 - labels)

    return(errors)

def pca_w2v(w2v, n_components):
    """
    Apply PCA on the embeddings on a SkipGram object.
    Parameters:
    - w2v (SkipGram): Pre-trained SkipGram
    - n_components (int): Number of components to keep
    Output:
    - new_w2v (SkipGram)
    """
    new_w2v = copy.deepcopy(w2v)
    pca = PCA(n_components)
    new_w2v.w1 = pca.fit_transform(new_w2v.w1.T)
    new_w2v.w1 = new_w2v.w1.T
    return(new_w2v)

def most_similar(sg, word):
    """
    Make it a static method
    """
    results = {}
    for w in sg.word2idx.keys():
        results[w] = sg.similarity(word, w)

    results = dict(sorted(results.items(), key=lambda x: x[1], reverse=True))

    return(results)

def simil(w2v, sent):
    try:
        return(w2v.similarity(sent[0], sent[1]))
    except:
        return(None)


"""Test optimization results."""
from pathlib import Path

import pytest

from sbmlsim.examples.experiments.midazolam.fitting_problems import op_mid1oh_iv
from sbmlsim.fit.analysis import OptimizationResult
from sbmlsim.fit.options import (
    OptimizationAlgorithmType,
    ResidualType,
    WeightingCurvesType,
    WeightingPointsType,
)
from sbmlsim.fit.runner import run_optimization

fit_kwargs_default = {
    "residual": ResidualType.ABSOLUTE,
    "weighting_curves": [WeightingCurvesType.POINTS],
    "weighting_points": WeightingPointsType.ERROR_WEIGHTING,
    "absolute_tolerance": 1e-6,
    "relative_tolerance": 1e-6,
}

@pytest.mark.skip(reason="no fit support")
def test_serialization(tmp_path: Path) -> None:
    """Test serialization of optimization result."""
    opt_res: OptimizationResult = run_optimization(
        problem=op_mid1oh_iv(),
        algorithm=OptimizationAlgorithmType.LEAST_SQUARE,
        size=1,
        n_cores=1,
        serial=True,
        **fit_kwargs_default
    )

    opt_res_path = tmp_path / "opt_res.json"
    opt_res.to_json(path=opt_res_path)
    opt_res2 = OptimizationResult.from_json(json_info=opt_res_path)

    assert opt_res.sid == opt_res2.sid
    assert [p.pid for p in opt_res.parameters] == [p.pid for p in opt_res2.parameters]

@pytest.mark.skip(reason="no fit support")
def test_combine(tmp_path: Path) -> None:
    """Test combination of optimization result."""
    opt_results = []
    for seed in [1234, 4567]:
        opt_res: OptimizationResult = run_optimization(
            problem=op_mid1oh_iv(),
            algorithm=OptimizationAlgorithmType.LEAST_SQUARE,
            size=1,
            n_cores=1,
            serial=True,
            seed=seed,
            **fit_kwargs_default
        )
        opt_results.append(opt_res)

    opt_result = OptimizationResult.combine(opt_results)
    assert len(opt_result.fits) == len(opt_results[0].fits) + len(opt_results[1].fits)


from rest_framework import serializers
from datetime import date,timedelta
from authen.models import *
from mahalla.models import *

class CategoriyaPeopleSerializers(serializers.ModelSerializer):
    class Meta:
        model = Categoriya
        fields = ['id','name']

class UserSektorSerializers(serializers.ModelSerializer):
    class Meta:
        model = CustumUsers
        fields = ['id','first_name','last_name','position','phone']

class RegionAllSerializers(serializers.ModelSerializer):
    class Meta:
        model = Region
        fields = ['id','name']

class MahallaAllSerializers(serializers.ModelSerializer):
    class Meta:
        model = Mahalla
        fields = ['id','name','id_sektor']

class SektorSerializers(serializers.ModelSerializer):
    class Meta:
        model = Sektor
        fields = ['id','name']

class DistirckSerializers(serializers.ModelSerializer):
    id_sektor = SektorSerializers(read_only=True,many=True)
    class Meta:
        model = District
        fields = ['id','name','id_sektor']

class TaslCategoriyaSerializers(serializers.ModelSerializer):
    class Meta:
        model = TaskCategoriya
        fields = '__all__'

class TaskPeopleSerializers(serializers.ModelSerializer):
    id_user = UserSektorSerializers(read_only=True)
    id_task_category = TaslCategoriyaSerializers(read_only=True)
    class Meta:
        model = Tasks
        fields = '__all__'

class PeopleAllSerializers(serializers.ModelSerializer):
    id_categor = CategoriyaPeopleSerializers(read_only=True)
    responsible_employee = UserSektorSerializers(read_only=True)
    id_mahalla = MahallaAllSerializers(read_only=True)
    id_region = RegionAllSerializers(read_only=True)
    id_sektor = SektorSerializers(read_only=True)
    id_districk = DistirckSerializers(read_only=True)
    people = TaskPeopleSerializers(many=True,read_only=True)
    class Meta:
        model = People
        fields = ('id','full_name','birth_date','phone','village','additional_information','id_categor','id_mahalla','id_sektor','id_region','id_districk','responsible_employee','create_user','people')

class PeopleCreateSerializers(serializers.ModelSerializer):
    class Meta:
        model = People
        fields = ['full_name','birth_date','phone','village','additional_information','id_categor','id_mahalla','id_sektor','id_region','id_districk','responsible_employee','create_user',]
    def create(self, validated_data):
        user_create = People.objects.create(**validated_data)
        user_create.id_mahalla = self.context.get('id_mahalla')
        user_create.id_sektor = self.context.get('id_sektor')
        user_create.id_region = self.context.get('id_region')
        user_create.id_districk = self.context.get('id_districk')
        user_create.create_user = self.context.get('create_user')
        user_create.save()
        return user_create

class TaskSerializers(serializers.ModelSerializer):
    class Meta:
        model = TaskCategoriya
        fields = ['id','name']

class TaskUser(serializers.ModelSerializer):
    class Meta:
        model = CustumUsers
        fields = ['id','first_name','last_name','phone','position']

class UserSerializersAll(serializers.ModelSerializer):
    class Meta:
        model = CustumUsers
        fields = ['id','first_name','last_name']

class TaskAllSerializers(serializers.ModelSerializer):
    id_user = TaskUser(read_only=True)
    class Meta:
        model = Tasks
        fields = '__all__'

class TaskCrudSerializers(serializers.ModelSerializer):
    class Meta:
        model = Tasks
        fields = ['id','id_people','id_task_category','id_user','task','is_user','comment','date_line']
    def create(self, validated_data):
        task_create = Tasks(
            id_task_category = validated_data['id_task_category'],
            id_user = validated_data['id_user'],
            task = validated_data['task'],
            comment = validated_data['comment']
        )
        task_create.id_people = self.context.get('id_people')
        for item in TaskCategoriya.objects.all():
            if validated_data['id_task_category'] == item:
                x = date.today()+timedelta(days=item.date)
        task_create.date_line = x
        task_create.save()
        return task_create

class TaskCreateFiles(serializers.ModelSerializer):
    class Meta:
        model = Tasks
        fields = ['id','id_people','files','is_user','is_task']
    def update(self, instance, validated_data):
        instance.files = validated_data.get('files',instance.files)
        instance.is_user = validated_data.get('is_user',instance.is_user)
        instance.save()
        return instance


import numpy as np
import torch
import torch.nn as nn

from libcity.model import loss
from libcity.model.abstract_traffic_state_model import AbstractTrafficStateModel

class SLSTM(nn.Module):
    def __init__(self, feature_dim, hidden_dim, device, p_interval):
        super(SLSTM, self).__init__()
        self.hidden_dim = hidden_dim
        self.cell_dim = hidden_dim
        self.p_interval = p_interval
        self.f_gate = nn.Sequential(
            nn.Linear(feature_dim + hidden_dim, self.cell_dim),
            nn.Softmax(dim=1)
        )
        self.i_gate = nn.Sequential(
            nn.Linear(feature_dim + hidden_dim, self.cell_dim),
            nn.Softmax(dim=1)
        )
        self.o_gate = nn.Sequential(
            nn.Linear(feature_dim + hidden_dim, self.hidden_dim),
            nn.Softmax(dim=1)
        )
        self.g_gate = nn.Sequential(
            nn.Linear(feature_dim + hidden_dim, self.cell_dim),
            nn.Tanh()
        )

        self.tanh = nn.Tanh()

        self.device = device

    def forward(self, x):
        # (T, B * N, 2E)
        h = torch.zeros((x.shape[1], self.hidden_dim)).unsqueeze(dim=0).repeat(self.p_interval, 1, 1).to(self.device)
        # (P, B * N, 2E)
        c = torch.zeros((x.shape[1], self.hidden_dim)).unsqueeze(dim=0).repeat(self.p_interval, 1, 1).to(self.device)
        # (P, B * N, 2E)

        T = x.shape[0]

        for t in range(T):
            x_ = x[t, :, :]  # (B * N, 2E)
            x_ = torch.cat((x_, h[t % self.p_interval]), 1)  # (B * N, 2E + 2E)

            f = self.f_gate(x_)  # (B * N, 2E)

            i = self.i_gate(x_)  # (B * N, 2E)

            o = self.o_gate(x_)  # (B * N, 2E)

            g = self.g_gate(x_)  # (B * N, 2E)

            c = f * c[t % self.p_interval] + i * g  # (B * N, 2E)

            c = self.tanh(c)  # (B * N, 2E)

            h[t % self.p_interval] = o * c  # (B * N, 2E)

        return h[(T - 1) % self.p_interval]  # (B * N, 2E)

class MutiLearning(nn.Module):
    def __init__(self, fea_dim, device):
        super(MutiLearning, self).__init__()
        self.fea_dim = fea_dim
        self.transition = nn.Parameter(data=torch.randn(self.fea_dim, self.fea_dim).to(device), requires_grad=True)
        self.project_in = nn.Parameter(data=torch.randn(self.fea_dim, 1).to(device), requires_grad=True)
        self.project_out = nn.Parameter(data=torch.randn(self.fea_dim, 1).to(device), requires_grad=True)

    def forward(self, x: torch.Tensor):
        # (B, N, 2E)
        x_t = x.permute(0, 2, 1)  # (B, 2E, N)

        x_in = torch.matmul(x, self.project_in)  # (B, N, 1)

        x_out = torch.matmul(x, self.project_out)  # (B, N, 1)

        x = torch.matmul(x, self.transition)
        # (B, N, 2E)
        x = torch.matmul(x, x_t)
        # (B, N, N)

        x = x.unsqueeze(dim=-1).unsqueeze(dim=1)
        x_in = x_in.unsqueeze(dim=-1).unsqueeze(dim=1)
        x_out = x_out.unsqueeze(dim=-1).unsqueeze(dim=1)

        return x, x_in, x_out

class GraphConvolution(nn.Module):
    def __init__(self, feature_dim, embed_dim, device, use_bias=False):
        super(GraphConvolution, self).__init__()
        self.feature_dim = feature_dim
        self.embed_dim = embed_dim
        self.activation = nn.ReLU()

        weight = torch.randn((self.feature_dim, self.embed_dim))
        self.weight = nn.Parameter(data=weight.to(device), requires_grad=True)
        if use_bias:
            self.bias = nn.Parameter(data=torch.zeros(self.embed_dim).to(device), requires_grad=True)
        else:
            self.bias = None

    def forward(self, x, a):
        # (B, N, N)
        embed = torch.matmul(a, x)
        # (B, N, N)
        embed = torch.matmul(embed, self.weight)
        # (B, N, E)
        if self.bias is not None:
            embed += self.bias

        return embed

class GCN(nn.Module):
    def __init__(self, feature_dim, embed_dim, device):
        super(GCN, self).__init__()
        self.feature_dim = feature_dim
        self.embed_dim = embed_dim
        self.gcn = nn.ModuleList([
            GraphConvolution(feature_dim, embed_dim, device),
            GraphConvolution(embed_dim, embed_dim, device)
        ])

    def forward(self, input_seq, adj_seq):
        embed = []
        for i in range(input_seq.shape[1]):
            frame = input_seq[:, i, :, :]  # (B, N, N)
            adj = adj_seq[:, i, :, :]  # (B, N, N)

            for m in self.gcn:
                frame = m(frame, adj)
            # (B, N, E)

            embed.append(frame)

        return torch.stack(embed, dim=1)

def generate_geo_adj(distance_matrix: np.matrix):
    distance_matrix = torch.Tensor(distance_matrix)  # (N, N)
    distance_matrix = distance_matrix * distance_matrix
    sum_cost_vector = torch.sum(distance_matrix, dim=1, keepdim=True)  # (N, 1)
    weight_matrix = distance_matrix / sum_cost_vector
    weight_matrix[range(weight_matrix.shape[0]), range(weight_matrix.shape[1])] = 1
    return weight_matrix  # (N, N)

def generate_semantic_adj(demand_matrix, device):
    # (B, T, N, N)
    adj_matrix = demand_matrix.clone()
    in_matrix = adj_matrix.permute(0, 1, 3, 2)

    adj_matrix[adj_matrix > 0] = 1

    adj_matrix[in_matrix > 0] = 1

    degree_vector = torch.sum(adj_matrix, dim=3, keepdim=True)
    # (B, T, N, 1)

    sum_degree_vector = torch.matmul(adj_matrix, degree_vector)
    # (B, T, N, 1)

    weight_matrix = torch.matmul(1 / (sum_degree_vector + 1e-3), degree_vector.permute((0, 1, 3, 2)))  # (B, T, N, N)

    weight_matrix[:, :, range(weight_matrix.shape[2]), range(weight_matrix.shape[3])] = 1

    return weight_matrix

class GEML(AbstractTrafficStateModel):
    def __init__(self, config, data_feature):
        super().__init__(config, data_feature)
        self.num_nodes = self.data_feature.get('num_nodes')
        self._scaler = self.data_feature.get('scaler')
        self.output_dim = config.get('output_dim')
        self.device = config.get('device', torch.device('cpu'))
        self.input_window = config.get('input_window', 1)
        self.output_window = config.get('output_window', 1)

        self.p_interval = config.get('p_interval', 1)
        self.embed_dim = config.get('embed_dim')
        self.batch_size = config.get('batch_size')
        self.loss_p0 = config.get('loss_p0', 0.5)
        self.loss_p1 = config.get('loss_p1', 0.25)
        self.loss_p2 = config.get('loss_p2', 0.25)

        dis_mx = self.data_feature.get('adj_mx')
        self.geo_adj = generate_geo_adj(dis_mx) \
            .repeat(self.batch_size * self.input_window, 1) \
            .reshape((self.batch_size, self.input_window, self.num_nodes, self.num_nodes)) \
            .to(self.device)

        self.GCN_ge = GCN(self.num_nodes, self.embed_dim, self.device)
        self.GCN_se = GCN(self.num_nodes, self.embed_dim, self.device)

        # self.LSTM = nn.LSTM(2 * self.embed_dim, 2 * self.embed_dim)
        self.LSTM = SLSTM(2 * self.embed_dim, 2 * self.embed_dim, self.device, self.p_interval)

        self.mutiLearning = MutiLearning(2 * self.embed_dim, self.device)

    def forward(self, batch):
        x = batch['X'].squeeze(dim=-1)
        # (B, T, N, N)
        x_ge_embed = self.GCN_ge(x, self.geo_adj[:x.shape[0], ...])
        # (B, T, N, E)

        x_se_embed = self.GCN_se(x, self.semantic_adj)

        # (B, T, N, E)
        x_embed = torch.cat([x_ge_embed, x_se_embed], dim=3)
        # (B, T, N, 2E)
        x_embed = x_embed.permute(1, 0, 2, 3)
        # (T, B, N, 2E)
        x_embed = x_embed.reshape((self.input_window, -1, 2 * self.embed_dim))
        # (T, B * N, 2E)

        # _, (h, _) = self.LSTM(x_embed)
        # x_embed_pred = h[0].reshape((self.batch_size, -1, 2 * self.embed_dim))
        x_embed_pred = self.LSTM(x_embed).reshape((x.shape[0], -1, 2 * self.embed_dim))
        # (B, N, 2E)

        out = self.mutiLearning(x_embed_pred)

        return out

    def calculate_loss(self, batch):
        y_true = batch['y']  # (B, TO, N, N, 1)
        y_in_true = torch.sum(y_true, dim=-2, keepdim=True)  # (B, TO, N, 1)
        y_out_true = torch.sum(y_true.permute(0, 1, 3, 2, 4), dim=-2, keepdim=True)  # (B, TO, N, 1)
        y_pred, y_in, y_out = self.predict(batch)

        y_true = self._scaler.inverse_transform(y_true[..., :self.output_dim])
        y_in_true = self._scaler.inverse_transform(y_in_true[..., :self.output_dim])
        y_out_true = self._scaler.inverse_transform(y_out_true[..., :self.output_dim])

        y_pred = self._scaler.inverse_transform(y_pred[..., :self.output_dim])
        y_in = self._scaler.inverse_transform(y_in[..., :self.output_dim])
        y_out = self._scaler.inverse_transform(y_out[..., :self.output_dim])

        loss_pred = loss.masked_mse_torch(y_pred, y_true)
        loss_in = loss.masked_mse_torch(y_in, y_in_true)
        loss_out = loss.masked_mse_torch(y_out, y_out_true)
        return self.loss_p0 * loss_pred + self.loss_p1 * loss_in + self.loss_p2 * loss_out

    def predict(self, batch):
        x = batch['X']  # (B, T, N, N, 1)
        self.semantic_adj = generate_semantic_adj(x.squeeze(dim=-1), self.device)
        assert x.shape[-1] == 1 or print("The feature_dim must be 1")
        y_pred = []
        y_in_pred = []
        y_out_pred = []
        x_ = x.clone()
        for i in range(self.output_window):
            batch_tmp = {'X': x_}
            y_, y_in_, y_out_ = self.forward(batch_tmp)  # (B, 1, N, N, 1)
            y_pred.append(y_.clone())
            y_in_pred.append(y_in_.clone())
            y_out_pred.append(y_out_.clone())

            x_ = torch.cat([x_[:, 1:, :, :, :], y_], dim=1)

        y_pred = torch.cat(y_pred, dim=1)  # (B, TO, N, N, 1)
        y_in_pred = torch.cat(y_in_pred, dim=1)  # (B, TO, N, 1)
        y_out_pred = torch.cat(y_out_pred, dim=1)  # (B, TO, N, 1)
        return y_pred, y_in_pred, y_out_pred


from rest_framework import status
from rest_framework.reverse import reverse_lazy
from rest_framework.test import APITestCase

from store.models import Book
from store.serializers import BooksSerializer
from store.tests.factories import BookFactory

class LogicTestCase(APITestCase):

    def setUp(self):
        self.book_1 = BookFactory(name='Book 1', price=25, author_name='Author 1')
        self.book_2 = BookFactory(name='Book 2', price=55, author_name='Author 5')
        self.book_3 = BookFactory(name='Book Author 1', price=55, author_name='Author 2')

    def test_list_01_url_exists_at_desired_location(self):
        response = self.client.get('/api/v1/book/')
        self.assertEqual(status.HTTP_200_OK, response.status_code)

    def test_list_02_url_accessible_by_name(self):
        response = self.client.get(reverse_lazy('store:book-list'))
        self.assertEqual(status.HTTP_200_OK, response.status_code)

    def test_list_03_get(self):
        books = Book.objects.all()
        serializer_data = BooksSerializer(books, many=True).data
        response = self.client.get(reverse_lazy('store:book-list'))
        self.assertEqual(status.HTTP_200_OK, response.status_code)

        self.assertEqual(serializer_data, response.data)

    def test_list_04_filter(self):
        serializer_data = BooksSerializer([self.book_2, self.book_3], many=True).data
        response = self.client.get(reverse_lazy('store:book-list'), data={'price': '55.00'})
        self.assertEqual(status.HTTP_200_OK, response.status_code)

        self.assertEqual(serializer_data, response.data)

    def test_list_05_search(self):
        serializer_data = BooksSerializer([self.book_1, self.book_3], many=True).data
        response = self.client.get(reverse_lazy('store:book-list'), data={'search': 'Author 1'})
        self.assertEqual(status.HTTP_200_OK, response.status_code)

        self.assertEqual(serializer_data, response.data)

    def test_list_06_ordering(self):
        books = Book.objects.order_by('-price').all()
        serializer_data = BooksSerializer(books, many=True).data
        response = self.client.get(reverse_lazy('store:book-list'), data={'ordering': '-price'})
        self.assertEqual(status.HTTP_200_OK, response.status_code)

        self.assertEqual(serializer_data, response.data)


from flask import render_template, redirect, url_for, flash, request
from flask_login import current_user, login_user, logout_user
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField
from wtforms.validators import ValidationError, DataRequired
from datetime import date
from .models.balance import Balance, Update_balance

from flask import Blueprint
bp = Blueprint('balance', __name__)

class balance_topup(FlaskForm):
	amount = StringField('amount', validators=[DataRequired()])
	submit = SubmitField('Top up')

class balance_withdraw(FlaskForm):
	amount = StringField('amount', validators=[DataRequired()])
	submit = SubmitField('Withdraw')

@bp.route('/my-balance')
def my_balance():
	balance_info = Balance.get(current_user.id)
	balance_info_all = Balance.get_all(current_user.id)

	return render_template('customer_my_balance.html', balance_info=balance_info, balance_info_all=balance_info_all)

@bp.route('/my-balance/withdraw', methods=('GET', 'POST'))
def my_balance_withdraw():
	balance_info = Balance.get(current_user.id)

	form = balance_withdraw()
	if form.validate_on_submit():
		trans_date = date.today()
		user_id = current_user.id
		trans = form.amount.data
		trans_description = 'Withdraw from bank account'
		balance = float(balance_info.balance) - float(trans)
		if balance < 0:
			flash('Withdrawal fail! (You can withdraw up to the available balance)')
			return redirect(url_for('balance.my_balance_withdraw'))

		else:
			Update_balance.insert(trans_date, user_id, -float(trans), trans_description, balance)
			balance_info = Balance.get(current_user.id)

			flash('Withdrawal successful!')
			return render_template('customer_my_balance_withdraw.html', balance_info = balance_info, form=form)

	return render_template('customer_my_balance_withdraw.html', balance_info = balance_info, form=form)

@bp.route('/my-balance/topup', methods=('GET', 'POST'))
def my_balance_topup():
	balance_info = Balance.get(current_user.id)

	form = balance_topup()
	if form.validate_on_submit():
		trans_date = date.today()
		user_id = current_user.id
		trans = form.amount.data
		balance = float(balance_info.balance) + float(trans)
		trans_description ='Deposit from bank account'

		Update_balance.insert(trans_date, user_id, trans, trans_description, balance)
		balance_info = Balance.get(current_user.id)

		flash('Topup successful!')

		return render_template('customer_my_balance_topup.html', balance_info = balance_info, form=form)

	return render_template('customer_my_balance_topup.html', balance_info = balance_info, form=form)


import nltk

def extract_entities(text):
    tokens = nltk.tokenize.casual_tokenize(text)
    tags = nltk.pos_tag(tokens)
    grammar = "NP: {<JJ>*(<NN>|<NNP>|<NNPS>|<NNS>)+}"
    parser = nltk.RegexpParser(grammar)
    result = parser.parse_all(tags)

    ret = []
    for item in result:
        if not hasattr(item, 'label'):
            assert len(item) == 2
            ret.append(item[0])
            continue
        assert item.label() == "NP"
        s = ' '.join([l[0] for l in item.leaves()])
        ret.append('{}'.format(s))

    return ret


# pymongoDB 사용을 위한 명령
from pymongo import MongoClient

# 로컬에서 돌아가는 mongoDB에 연결
client = MongoClient('localhost', 27017)
# dbsparta 이름을 가진 DB에 접속
db = client.dbsparta

# 웹스크래핑(크롤링 기초)
import requests  # 요청 명령 불러오기
from bs4 import BeautifulSoup  # bs4의 BeautifulSoup 불러오기

headers = {
	'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.86 Safari/537.36'}
data = requests.get('https://movie.naver.com/movie/sdb/rank/rmovie.nhn?sel=pnt&date=20200303', headers=headers)
#                       기본적인 요청을 막아둔 사이트를 우회하기 위해 브라우저 요청 효과를 주기 위해서 headers=headers 사용

soup = BeautifulSoup(data.text, 'html.parser')
# BeautifulSoup의 사용 방법 2가지
#   select_one : 한 개의 데이터 값을 불러오는 것
#   select : 여러개의 데이터를 List 형식으로 불러오는 것

# 코딩 시작
# title = soup.select_one('#old_content > table > tbody > tr:nth-child(2) > td.title > div > a')
# print(title)  # 태그 호출
# print(title.text)  # 태그 사이의 텍스트만 불러오고 싶을 경우 .text를 사용하여 원하는 텍스트 호출
# print(title['href'])  # 태그의 속성을 가져오고 싶을 경우 ['~~']의 ~~에 태그 속성 입력

# 페이지 크롤링 해보기
# old_content > table > tbody > tr
# 공통 selecter 선언
trs = soup.select('#old_content > table > tbody > tr')

for tr in trs:
	# print(tr)

	# 영화 이름
	# old_content > table > tbody > tr:nth-child(2) >
	a_tag = tr.select_one('td.title > div > a')
	# print(a_tag)

	if a_tag is not None:
		title = a_tag.text
		# print(rank['alt'])
		# print(title)
		# print(rate.text)
		# print(lank['alt'], title, rate.text)

		# 영화 랭킹 순위값 불러오기
		# old_content > table > tbody > tr:nth-child(2) >
		rank = tr.select_one('td:nth-child(1) > img')['alt']

		# 영화 평점
		# old_content > table > tbody > tr:nth-child(2) >
		rate = tr.select_one('td.point').text

		# DB에 크롤링한 영화 data 저장하기
		doc = {
			'rank': rank,
			'title': title,
			'star': rate
		}
		db.movies.insert_one(doc)