from dataclasses import dataclass
from typing import Optional

import django_tables2 as tables
from django.conf import settings
from django.contrib.auth.models import AnonymousUser
from django.db.models import DateField, DateTimeField
from django.template import Context, Template
from django.urls import reverse
from django.utils.encoding import escape_uri_path
from django.utils.formats import date_format
from django.utils.safestring import mark_safe
from django_tables2.columns import library

from utilities.utils import get_viewname, content_type_name, content_type_identifier

__all__ = (
    'ActionsColumn',
    'BooleanColumn',
    'ChoiceFieldColumn',
    'ColorColumn',
    'ColoredLabelColumn',
    'LinkedCountColumn',
    'ManyToManyColumn',
    'TagColumn',
    'TemplateColumn',
    'ToggleColumn',
    'UtilizationColumn',
    'TruncatedTextColumn',
    'ContentTypeColumn',
    'ContentTypesColumn',
)

#
# Django-tables2 overrides
#

@library.register
class DateColumn(tables.DateColumn):
    """
    Overrides the default implementation of DateColumn to better handle null values, returning a default value for
    tables and null when exporting data. It is registered in the tables library to use this class instead of the
    default, making this behavior consistent in all fields of type DateField.
    """
    def value(self, value):
        return value

    @classmethod
    def from_field(cls, field, **kwargs):
        if isinstance(field, DateField):
            return cls(**kwargs)

@library.register
class DateTimeColumn(tables.DateTimeColumn):
    """
    Overrides the default implementation of DateTimeColumn to better handle null values, returning a default value for
    tables and null when exporting data. It is registered in the tables library to use this class instead of the
    default, making this behavior consistent in all fields of type DateTimeField.
    """
    def value(self, value):
        if value:
            return date_format(value, format="SHORT_DATETIME_FORMAT")
        return None

    @classmethod
    def from_field(cls, field, **kwargs):
        if isinstance(field, DateTimeField):
            return cls(**kwargs)

class ManyToManyColumn(tables.ManyToManyColumn):
    """
    Overrides django-tables2's stock ManyToManyColumn to ensure that value() returns only plaintext data.
    """
    def value(self, value):
        items = [self.transform(item) for item in self.filter(value)]
        return self.separator.join(items)

class TemplateColumn(tables.TemplateColumn):
    """
    Overrides django-tables2's stock TemplateColumn class to render a placeholder symbol if the returned value
    is an empty string.
    """
    PLACEHOLDER = mark_safe('—')

    def __init__(self, export_raw=False, **kwargs):
        """
        Args:
            export_raw: If true, data export returns the raw field value rather than the rendered template. (Default:
                        False)
        """
        super().__init__(**kwargs)
        self.export_raw = export_raw

    def render(self, *args, **kwargs):
        ret = super().render(*args, **kwargs)
        if not ret.strip():
            return self.PLACEHOLDER
        return ret

    def value(self, **kwargs):
        if self.export_raw:
            # Skip template rendering and export raw value
            return kwargs.get('value')

        ret = super().value(**kwargs)
        if ret == self.PLACEHOLDER:
            return ''
        return ret

#
# Custom columns
#

class ToggleColumn(tables.CheckBoxColumn):
    """
    Extend CheckBoxColumn to add a "toggle all" checkbox in the column header.
    """
    def __init__(self, *args, **kwargs):
        default = kwargs.pop('default', '')
        visible = kwargs.pop('visible', False)
        if 'attrs' not in kwargs:
            kwargs['attrs'] = {
                'td': {
                    'class': 'whitespace-nowrap px-3 py-4 text-gray-500',
                },
                'input': {
                    'class': 'h-4 w-4 rounded border-gray-300 text-indigo-600'
                }
            }
        super().__init__(*args, default=default, visible=visible, **kwargs)

    @property
    def header(self):
        return mark_safe('<input type="checkbox" class="toggle h-4 w-4 rounded border-gray-300 text-indigo-600" title="Toggle All" />')

class BooleanColumn(tables.Column):
    """
    Custom implementation of BooleanColumn to render a nicely-formatted checkmark or X icon instead of a Unicode
    character.
    """
    def render(self, value):
        if value:
            rendered = ''
        elif value is None:
            rendered = '—'
        else:
            rendered = ''
        return mark_safe(rendered)

    def value(self, value):
        return str(value)

@dataclass
class ActionsItem:
    title: str
    icon: str
    permission: Optional[str] = None
    css_class: Optional[str] = 'bg-zinc-500 hover:bg-zinc-400'

class ActionsColumn(tables.Column):
    """
    A dropdown menu which provides edit, delete, and changelog links for an object. Can optionally include
    additional buttons rendered from a template string.

    :param actions: The ordered list of dropdown menu items to include
    :param extra_buttons: A Django template string which renders additional buttons preceding the actions dropdown
    :param split_actions: When True, converts the actions dropdown menu into a split button with first action as the
        direct button link and icon (default: True)
    """
    attrs = {'td': {'class': 'whitespace-nowrap px-3 py-4 text-right text-black dark:text-gray-200 print:hidden'}}
    empty_values = ()
    actions = {
        'edit': ActionsItem('Edit', 'pencil', 'change', 'bg-yellow-500 hover:bg-yellow-400'),
        'delete': ActionsItem('Delete', 'trash-can-outline', 'delete', 'bg-red-500 hover:bg-red-400'),
        'changelog': ActionsItem('Changelog', 'history'),
    }

    def __init__(self, *args, actions=('edit', 'delete', 'changelog'), extra_buttons='', split_actions=True, **kwargs):
        super().__init__(*args, **kwargs)

        self.extra_buttons = extra_buttons
        self.split_actions = split_actions

        # Determine which actions to enable
        self.actions = {
            name: self.actions[name] for name in actions
        }

    def header(self):
        return ''

    def render(self, record, table, **kwargs):
        # Skip dummy records (e.g. available VLANs) or those with no actions
        if not getattr(record, 'pk', None) or (not self.actions and not self.extra_buttons):
            return ''

        model = table.Meta.model
        request = getattr(table, 'context', {}).get('request')
        url_appendix = f'?return_url={escape_uri_path(request.get_full_path())}' if request else ''
        html = ''

        buttons = []
        user = getattr(request, 'user', AnonymousUser())
        for idx, (action, attrs) in enumerate(self.actions.items()):
            permission = f'{model._meta.app_label}.{attrs.permission}_{model._meta.model_name}'
            if attrs.permission is None or user.has_perm(permission):
                url = reverse(get_viewname(model, action), kwargs={'pk': record.pk})

                buttons.append(
                    f''
                    f''
                )

        rendered_extra_buttons = ''

        # Render any extra buttons from template code
        if self.extra_buttons:
            template = Template(self.extra_buttons)
            context = getattr(table, "context", Context())
            context.update({'record': record})
            rendered_extra_buttons = template.render(context) + html

        html += (
            f'
'
            f'  {rendered_extra_buttons}'
            f'  {"".join(buttons)}'
            f'
'
        )

        return mark_safe(html)

class ChoiceFieldColumn(tables.Column):
    """
    Render a model's static ChoiceField with its value from `get_FOO_display()` as a colored badge. Background color is
    set by the instance's get_FOO_color() method, if defined.
    """
    DEFAULT_BG_COLOR = 'bg-gray-500'

    def render(self, record, bound_column, value):
        if value in self.empty_values:
            return self.default

        # Determine the background color to use (try calling object.get_FOO_color())
        try:
            bg_color = getattr(record, f'get_{bound_column.name}_color')() or self.DEFAULT_BG_COLOR
        except AttributeError:
            bg_color = self.DEFAULT_BG_COLOR

        return mark_safe(f'{value}')

    def value(self, value):
        return value

class ContentTypeColumn(tables.Column):
    """
    Display a ContentType instance.
    """
    def render(self, value):
        if value is None:
            return None
        return content_type_name(value)

    def value(self, value):
        if value is None:
            return None
        return content_type_identifier(value)

class ContentTypesColumn(tables.ManyToManyColumn):
    """
    Display a list of ContentType instances.
    """
    def __init__(self, separator=None, *args, **kwargs):
        # Use a line break as the default separator
        if separator is None:
            separator = mark_safe('
')
        super().__init__(separator=separator, *args, **kwargs)

    def transform(self, obj):
        return content_type_name(obj, include_app=False)

    def value(self, value):
        return ','.join([
            content_type_identifier(ct) for ct in self.filter(value)
        ])

class ColorColumn(tables.Column):
    """
    Display an arbitrary color value, specified in RRGGBB format.
    """
    def render(self, value):
        return mark_safe(
            f' '
        )

    def value(self, value):
        return f'#{value}'

class ColoredLabelColumn(tables.TemplateColumn):
    """
    Render a related object as a colored label. The related object must have a `color` attribute (specifying
    an RRGGBB value) and a `get_absolute_url()` method.
    """
    template_code = """
{% load helpers %}
  {% if value %}

    {{ value }}

{% else %}
  —
{% endif %}
"""

    def __init__(self, *args, **kwargs):
        super().__init__(template_code=self.template_code, *args, **kwargs)

    def value(self, value):
        return str(value)

class LinkedCountColumn(tables.Column):
    """
    Render a count of related objects linked to a filtered URL.

    :param viewname: The view name to use for URL resolution
    :param view_kwargs: Additional kwargs to pass for URL resolution (optional)
    :param url_params: A dict of query parameters to append to the URL (e.g. ?foo=bar) (optional)
    """
    def __init__(self, viewname, *args, view_kwargs=None, url_params=None, default=0, **kwargs):
        self.viewname = viewname
        self.view_kwargs = view_kwargs or {}
        self.url_params = url_params
        super().__init__(*args, default=default, **kwargs)

    def render(self, record, value):
        if value:
            url = reverse(self.viewname, kwargs=self.view_kwargs)
            if self.url_params:
                url += '?' + '&'.join([
                    f'{k}={getattr(record, v) or settings.FILTERS_NULL_CHOICE_VALUE}'
                    for k, v in self.url_params.items()
                ])
            return mark_safe(f'{value}')
        return value

    def value(self, value):
        return value

class TagColumn(tables.TemplateColumn):
    """
    Display a list of Tags assigned to the object.
    """
    template_code = """
    {% load helpers %}
    {% for tag in value.all %}
        {% tag tag url_name %}
    {% empty %}
        —
    {% endfor %}
    """

    def __init__(self, url_name=None):
        super().__init__(
            orderable=False,
            template_code=self.template_code,
            extra_context={'url_name': url_name}
        )

    def value(self, value):
        return ",".join([tag.name for tag in value.all()])

class UtilizationColumn(tables.TemplateColumn):
    """
    Display a colored utilization bar graph.
    """
    template_code = """{% load helpers %}{% if record.pk %}{% utilization_graph value %}{% endif %}"""

    def __init__(self, *args, **kwargs):
        super().__init__(template_code=self.template_code, *args, **kwargs)

    def value(self, value):
        return f'{value}%'

class MarkdownColumn(tables.TemplateColumn):
    """
    Render a Markdown string.
    """
    template_code = """
    {% if value %}
      {{ value|markdown }}
    {% else %}
      —
    {% endif %}
    """

    def __init__(self):
        super().__init__(
            template_code=self.template_code
        )

    def value(self, value):
        return value

class TruncatedTextColumn(tables.Column):
    """A Column to limit to 100 characters and add an ellipsis"""
    def render(self, value):
        if len(value) > 52:
            return value[0:49] + '...'
        return str(value)


import numpy as np
from scipy import misc
import pandas as pd
import os

# 1) Examen

## 2) Crear un vector de ceros de tamaño 10

vector_zeros_2 = np.zeros(10)
print('2) --> ', vector_zeros_2)

## 3) Crear un vector de ceros de tamaño 10 y el de la posicion 5 sea igual a 1

vector_zeros_3 = np.zeros(10)
vector_zeros_3[5] = 1

print('3) --> ', vector_zeros_3)

## 4) Cambiar el orden de un vector de 50 elementos, el de la posicion 1 es el de la 50 etc.

vector_zeros_4 = np.arange(50)
vector_zeros_4 = vector_zeros_4[::-1]

print('4) --> ', vector_zeros_4)

## 5) Crear una matriz de 3 x 3 con valores del cero al 8

matriz = np.arange(9)
matriz = matriz.reshape((3,3))

print('5) --> ', matriz)

## 6) Encontrar los indices que no sean cero en un arreglo

arreglo_indices = [1,2,0,0,4,0]
arreglo_indices = np.array(arreglo_indices)

resultado = np.where(arreglo_indices != 0)[0]

print('6) --> ', resultado)

## 7) Crear una matriz de identidad 3 x 3

matriz_identidad = np.eye(3)
print('7) --> ', matriz_identidad)

## 8) Crear una matriz 3 x 3 x 3 con valores randomicos

matriz_randomica = np.random.randint(27, size=27).reshape(3,3,3)
print('8) --> ', matriz_randomica)

## 9) Crear una matriz 10 x 10 y encontrar el mayor y el menor

matriz_diez = np.arange(100).reshape(10,10)

menor_valor = matriz_diez.min()
mayor_valor = matriz_diez.max()

print('9) menor --> ', menor_valor)
print('9) mayor --> ', mayor_valor)

## 10) Sacar los colores RGB unicos en una imagen (cuales rgb existen ej: 0, 0, 0 - 255,255,255 -> 2 colores)

imagen = misc.face()

resultado = len(np.unique(imagen, axis=0))
print('10) --> ', resultado)

## 11) ¿Como crear una serie de una lista, diccionario o arreglo?

mylist = list('abcdefghijklmnsopqrstuvwxyz')
myarr = np.arange(26)
mydict = dict(zip(mylist, myarr))

serie = pd.Series(mylist)
serie_diccionario = pd.Series(mydict)
serie_arreglo = pd.Series(myarr)

print('11) --> Serie de lista: ', serie, '\n')
print('11) --> Serie de diccionario: ', serie_diccionario, '\n')
print('11) --> Serie de arreglo ', serie_arreglo, '\n')

## 12) ¿Como convertir el indice de una serie en una columna de un DataFrame?

mylist = list('abcedfghijklmnopqrstuvwxyz')
myarr = np.arange(26)
mydict = dict(zip(mylist, myarr))
ser = pd.Series(mydict)

df = pd.DataFrame(ser).reset_index()

# Transformar la serie en dataframe y hacer una columna indice

df1 = pd.DataFrame(ser, index=['a'])

## 13) ¿Como combinar varias series para hacer un DataFrame?

ser1 = pd.Series(list('abcedfghijklmnopqrstuvwxyz'))
ser2 = pd.Series(np.arange(26))

df_combinado = pd.concat([ser1, ser2], axis = 1)
df_combinado = pd.DataFrame(df_combinado)

print('13) --> ', df_combinado)

## 14) ¿Como obtener los items que esten en una serie A y no en una serie B?

ser1 = pd.Series([1, 2, 3, 4, 5])
ser2 = pd.Series([4, 5, 6, 7, 8])

items_diferencia = np.setdiff1d(ser1, ser2)
print('14) --> ', items_diferencia)

## 15) ¿Como obtener los items que no son comunes en una serie A y serie B?

ser1 = pd.Series([1, 2, 3, 4, 5])
ser2 = pd.Series([4, 5, 6, 7, 8])

items_conjuncion = set(ser1) ^ set(ser2)
items_conjuncion = list(items_conjuncion)
items_conjuncion = pd.Series(items_conjuncion)

print('15) --> ', items_conjuncion, '\n')

## 16) ¿Como obtener el numero de veces que se repite un valor en una serie?

ser = pd.Series(np.take(list('abcdefgh'), np.random.randint(8, size=30)))

repeticiones, contador = np.unique(ser, return_counts=True)
repeticiones = dict(zip(repeticiones, contador))

print(repeticiones)
print(contador)

print('16) --> ', repeticiones, '\n')

## 17) ¿Como mantener los 2 valores mas repetidos de una serie, y a los demas valores cambiarles por 0 ?

np.random.RandomState(100)
ser = pd.Series(np.random.randint(1, 5, [12]))

valores_repetidos, contador = np.unique(ser, return_counts=True)

print('serie --> ', ser)
print('contador --> ', ser)
indice = np.argsort(-contador)
print('indice --> ', indice)
valores_repetidos = valores_repetidos[indice]

valores_repetidos[2:] = 0

print('17) --> Valores repetidos', valores_repetidos)

## 18) ¿Como transformar una serie de un arreglo de numpy a un DataFrame con un `shape` definido?

ser = pd.Series(np.random.randint(1, 10, 35))

df_shape = pd.DataFrame(ser.values.reshape(7,5))

print('18) --> ', df_shape)

## 19) ¿Obtener los valores de una serie conociendo la posicion por indice?

ser = pd.Series(list('abcdefghijklmnopqrstuvwxyz'))
pos = [0, 4, 8, 14, 20]
# a e i o u

resultado = ser[pos]

print('19) --> ', resultado)

## 20) ¿Como anadir series vertical u horizontalmente a un DataFrame?

ser1 = pd.Series(range(5))
ser2 = pd.Series(list('abcde'))

#Verical
df1 = pd.concat([pd.DataFrame(),ser2], ignore_index = True)

#Horizontal
df2 = pd.DataFrame().append(ser1, ignore_index=True)

print('20) Vertical --> ', df1)
print('21) Horizontal --> ', df2)

## 21)¿Obtener la media de una serie agrupada por otra serie?

#`groupby` tambien esta disponible en series.

frutas = pd.Series(np.random.choice(['manzana', 'banana', 'zanahoria'], 10))
pesos = pd.Series(np.linspace(1, 10, 10))
print(pesos.tolist())
print(frutas.tolist())
#> [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0]
#> ['banana', 'carrot', 'apple', 'carrot', 'carrot', 'apple', 'banana', 'carrot', 'apple', 'carrot']

# Los valores van a cambiar por ser random
# apple     6.0
# banana    4.0
# carrot    5.8
# dtype: float64

media_agrupada = pd.concat([frutas, pesos], axis = 1)
media_agrupada = media_agrupada.groupby(media_agrupada[0], as_index=False)[1].mean()

print('21) --> \n', media_agrupada)

## 22)¿Como importar solo columnas especificas de un archivo csv?

#https://raw.githubusercontent.com/selva86/datasets/master/BostonHousing.csv.

path = "./archivo.csv"

data_csv = pd.read_csv(
    path,
    nrows = 10)

columnas = ['crim', 'zn', 'indus']

data_tres_columnas = pd.read_csv(path, nrows=10, usecols=columnas)

print('22) --> ', data_tres_columnas)


from aiogram import Bot, types
from aiogram.dispatcher import Dispatcher
from aiogram.dispatcher import FSMContext
from aiogram.utils import executor
from aiogram.dispatcher.filters.state import State, StatesGroup
from aiogram.contrib.fsm_storage.memory import MemoryStorage
import logging
import sqlite3

from aiogram.types import ReplyKeyboardRemove, \
    ReplyKeyboardMarkup, KeyboardButton, \
    InlineKeyboardMarkup, InlineKeyboardButton

from config import TOKEN
import text_or_question as text
import keaboard as kb
import time
import datetime
import asyncio

from db_admin import DateBase

from sqlit import reg_user,obnova_members_status,count_member_in_status,info_members,send_status_no_rassilka,cheack_status

datebase = DateBase('users.db')

bot = Bot(token=TOKEN)
db = Dispatcher(bot, storage=MemoryStorage())
logging.basicConfig(level=logging.INFO)

class st_reg(StatesGroup):
    st_name = State()
    st_fname = State()
    step_q = State()
    step_regbutton = State()

user_list1 = []
user_list2 = []
user_list3 = []
user_list4 = []
user_list5 = []
user_list6 = []
user_list7 = []
user_list8 = []

class Form(StatesGroup):
    info_text = State()
    user_delete = State()

ADMIN_ID_1 = 494588959 #Cаня
ADMIN_ID_2 = 44520977 #Коля
ADMIN_ID_3 = 678623761 #Бекир
ADMIN_ID_4 = 941730379 #Джейсон
ADMIN_ID_5 = 807911349 #Байзат
ADMIN_ID_6 = 1045832338 #Коля 2 (НИКОЛА_ОДНОУС)

ADMIN = [ADMIN_ID_1,ADMIN_ID_2,ADMIN_ID_3,ADMIN_ID_4,ADMIN_ID_5,ADMIN_ID_6]

user_1 = '@nikolanext' #ДЛЯ ТЕХ, КТО ПЛАТНЫЙ (1)
user02349 = '@NikolaOdnous' #ДЛЯ ТЕХ, КТО НЕ (1)

@db.message_handler(commands=['start'])
async def greetings(message: types.Message):

    user_id = message.chat.id
    reg_user(user_id,0) #Записываем в базу человека со статусом 0

    m = await message.answer_photo(text.hi_photo_id, caption=text.hi_text, reply_markup=kb.the_first_go_button)

    go_new = 'Г'
    for i in range(1,14):
        go_new+='о'
        await bot.edit_message_caption(chat_id=user_id,message_id=m.message_id,caption=text.hi_text.format(go_new),reply_markup=kb.the_first_go_button)
        await asyncio.sleep(0.43)

@db.message_handler(commands=['admin'])
async def vienw_adminka(message: types.Message):
    if message.chat.id in ADMIN:
        button1 = KeyboardButton('📊Статистика всех пользователей')

        button2 = KeyboardButton('💿База данных')
        button3 = KeyboardButton('🔫Удаление челов')

        button4 = KeyboardButton('🆓Рассылка бесплатникам')
        button5 = KeyboardButton('💰Рассылка платникам')

        markup3 = ReplyKeyboardMarkup(resize_keyboard=True)
        markup3 = markup3.add(button1)
        markup3 = markup3.add(button2,button3)
        markup3 = markup3.add(button4,button5)

        await bot.send_message(chat_id=message.chat.id,text='Открыта админка 🔘',reply_markup=markup3)

@db.message_handler(state=Form.user_delete,content_types=['video','voice','photo','video_note','file','document','text'])
async def delete_user(message: types.Message, state: FSMContext):
    try:
        user_id = message.forward_from.id
        send_status_no_rassilka(user_id)
    except Exception as e:
        print(e)

    markup = types.InlineKeyboardMarkup()
    bat_otmena12 = types.InlineKeyboardButton(text='Выйти из режима удаления',callback_data='exit_del')
    markup.add(bat_otmena12)

    await message.answer('Пользователь удалён 🩸',reply_markup=markup)

@db.message_handler(state=Form.info_text, content_types=['text', 'photo', 'video_note', 'video', 'voice'])
async def send_mailing_text(message: types.Message, state: FSMContext):
    if message.text == 'отмена':
        await state.finish()
        await message.answer('Отменено')
    if message.text or message.photo or message.video:
        for user_id in datebase.mailing_user_id():
            if message.text and message.photo:
                await bot.send_photo(user_id[1], message.photo[2].file_id, caption=message.text)
            elif message.text and message.video:
                await bot.send_video(user_id[1], message.video.file_id, caption=message.text)
            elif message.photo:
                await bot.send_photo(user_id[1], message.photo[2].file_id)
            elif message.video:
                await bot.send_video(user_id[1], message.video.file_id)
            elif message.text:
                await bot.send_message(user_id[1], message.text)
    elif message.video_note:
        for user_id in datebase.mailing_user_id():
            await bot.send_video_note(user_id[1], message.video_note.file_id)
    elif message.voice:
        for user_id in datebase.mailing_user_id():
            await bot.send_voice(user_id[1], message.voice.file_id)
    await message.answer('Рассылка произведена.')
    await message.answer(f'Рассылку получили {datebase.count_string2()} из {datebase.count_string()}')
    await state.finish()

@db.callback_query_handler(lambda call: True, state = '*')
async def answer_push_inline_button(call, state: FSMContext):
    global user_list1
    user_id = call.message.chat.id # ЮЗЕР ЧЕЛА
    status = (cheack_status(user_id))[0]
    if status == 1:
        username_contact = user_1
    else:
        username_contact = user02349

    if call.data == 'go_button':
        await state.finish()
        await bot.send_message(chat_id=call.message.chat.id,text='Отменено. Включен обычный режим✅')
    if call.data == 'go_button':
        await call.message.answer_video_note(text.video_note_id, reply_markup=kb.pass_the_five_question)
    elif call.data == 'five_question':
        await call.message.answer_animation(text.the_first_question_gif_id, caption=text.the_first_question_text,
                                            reply_markup=kb.first_question_buttons)
    elif call.data == 'first_question':
        await call.message.delete()
        await call.message.answer_animation(text.the_second_question_gif_id, caption=text.the_second_question_text,
                                            reply_markup=kb.second_question_buttons)
    elif call.data == 'second_question':
        await call.message.delete()
        await call.message.answer_animation(text.the_third_question_gif_id, caption=text.the_third_question_text,
                                            reply_markup=kb.third_question_buttons)
    elif call.data == 'third_question':
        await call.message.delete()
        await call.message.answer_animation(text.the_fourth_question_gif_id, caption=text.the_fourth_question_text,
                                            reply_markup=kb.fourth_question_buttons)

    elif call.data[:15] == 'fourth_question':
        if call.data == 'fourth_question1': # Человек из рекламы инст
            obnova_members_status(call.message.chat.id, 1)
        if call.data == 'fourth_question2': # Человек из ТикТока
            obnova_members_status(call.message.chat.id, 2)
        if call.data == 'fourth_question3': # Человек из Рилса
            obnova_members_status(call.message.chat.id, 3)
        if call.data == 'fourth_question4': # Другое
            obnova_members_status(call.message.chat.id, 4)

        await call.message.delete()
        await call.message.answer_animation(text.the_five_question_gif_id, caption=text.the_five_question_text,
                                            reply_markup=kb.five_question_buttons)

    elif call.data == 'five_questions':
        await call.message.delete()
        await call.message.answer('🕺🏻А вот и обещанный бонус 🕺🏻')
        await call.message.answer_document(text.bonus_dock_file_id)
        await call.message.answer_photo(text.finished_text_file_id, caption=text.finished_text, reply_markup=kb.finished_text_button)

    elif call.data == 'go_2':
        await call.message.answer_video('BAACAgIAAxkBAAMmYV1W4yEZI3tZMuEFt7TzpRXmTtMAAskPAALV8iFKl-Icg7tg87IhBA')
        # await call.message.answer('Первое видео')
        await asyncio.sleep(78)#60
        await call.message.answer(text='Жмякай кнопку пока не убежала👇', reply_markup=kb.further_button)

    elif call.data == 'further':
        await call.message.answer_video('BAACAgIAAxkBAAMoYV1XarMS_OoOn_Vwr3oJ9liOtPkAAogVAALalClKikrq4brnf-0hBA')
        # await call.message.answer('Второе видео')
        await asyncio.sleep(136)#136
        await call.message.answer(text='Жмякай кнопку пока не убежала👇', reply_markup=kb.futher2_button)

    elif call.data == 'further2':
        await call.message.answer_video(f'BAACAgIAAxkBAAMqYV1XrtFkA-VnlCNrx2scKWuU6pUAAp0TAAKBgcBKIdx8Ive5nrYhBA')
        # await call.message.answer('Третье видео')
        await asyncio.sleep(205)#205
        await call.message.answer(text.last_text.format(username_contact))
        user_id = call.message.chat.id
        username = call.message.from_user.username

        # Если рассылка человек не состоит ни в одной из группе, то добалвяем его в первую
        if (user_id not in user_list1) and (user_id not in user_list2) and (user_id not in user_list3) and (user_id not in user_list4) and (user_id not in user_list5) and (user_id not in user_list6) and (user_id not in user_list7) and (user_id not in user_list8):
            #ЕСЛИ ЧЕЛА НЕТУ НИ В ОДНОЙ ИЗ ГРУПП ДЛЯ ПРОГРЕВА, ТО:
            user_list1.append(user_id)
            try:
                datebase.records_of_mailing_users(username, user_id)
            except Exception as e:
                print(e)

@db.message_handler(content_types=['text', 'photo', 'video_note', 'animation', 'document', 'video','file'])
async def all_message(message: types.Message, state: FSMContext):
    # try:
    #     print(message.video.file_id)
    # except:
    #     pass
    #
    # try:
    #     print(message.photo[2].file_id)
    # except:
    #     pass
    #
    # try:
    #     print(message.video_note.file_id)
    # except:
    #     pass
    #
    # try:
    #     print(message.animation.file_id)
    # except:
    #     pass
    #
    # try:
    #     print(message.document.file_id)
    # except:
    #     pass
    #
    if message.chat.id in ADMIN:

        if message.text == '📊Статистика всех пользователей':
            all = info_members()# Всего пользователей
            s1 = count_member_in_status(1)
            s2 = count_member_in_status(2)
            s3 = count_member_in_status(3)
            s4 = count_member_in_status(4)

            s0 = count_member_in_status(0) #Еще не выбрпали ответ

            await bot.send_message(chat_id=message.chat.id,text=f"""<b>👥Всего пользователей: {all}</b>

1⃣Пользователей из инсты: {s1}
2⃣Пользователей из ТикТока : {s2}
3⃣Пользователей из Рилса: {s3}
4⃣Пользователей из «Другого»: {s4}

🟡Еще не выбрали ответ: {s0}""",parse_mode='html')

        if message.text == '💿База данных':
            await message.answer_document(open("server.db", "rb"))

        if message.text == '🔫Удаление челов':
            await message.answer('👺Включен режим удаление челов \n'
                                 '🔙Для выхода, напиши "отмена"')
            await Form.user_delete.set()

        if message.text == '🆓Рассылка бесплатникам': #Рассылка по группе 2,3,4,0
            murkap = types.InlineKeyboardMarkup()
            bat0 = types.InlineKeyboardButton(text='ОТМЕНА', callback_data='otemena')
            murkap.add(bat0)
            await bot.send_message(message.chat.id, 'Перешли мне уже готовый пост и я разошлю его всем юзерам',
                                   reply_markup=murkap)
            await st_reg.step_q.set()

            await state.update_data(type_rassilki = 2340) # ТИП расслыки по 2,3,4,0 группе

        if message.text == '💰Рассылка платникам': #Рассылка по группе 1
            murkap = types.InlineKeyboardMarkup()
            bat0 = types.InlineKeyboardButton(text='ОТМЕНА', callback_data='otemena')
            murkap.add(bat0)
            await bot.send_message(message.chat.id, 'Перешли мне уже готовый пост и я разошлю его всем юзерам',
                                   reply_markup=murkap)
            await st_reg.step_q.set()

            await state.update_data(type_rassilki=1) # ТИП расслыки по первой группе

#ПРОГРЕВ
async def send_to_a_certain_hour():
    while True:

        offset = datetime.timezone(datetime.timedelta(hours=3))
        now_time = datetime.datetime.now(offset)

        if now_time.hour == 16:
            for user7 in user_list7:
                status = (cheack_status(user7))[0]
                if status == 1:
                    username_contact = user_1
                else:
                    username_contact = user02349
                if status != 9:
                    await bot.send_message(user7, text=text.dayly_text7.format(username_contact))
                    user_list7.remove(user7)
                    user_list8.append(user7)

            for user6 in user_list6:
                status = (cheack_status(user6))[0]
                if status == 1:
                    username_contact = user_1
                else:
                    username_contact = user02349
                if status != 9:
                    await bot.send_photo(user6, photo=text.dayly_photo_id6, caption=text.dayly_text6.format(username_contact))
                    user_list7.append(user6)
                    user_list6.remove(user6)

            for user5 in user_list5:
                status = (cheack_status(user5))[0]
                if status == 1:
                    username_contact = user_1
                else:
                    username_contact = user02349

                if status != 9:
                    await bot.send_photo(user5, photo=text.dayly_photo_id5, caption=text.dayly_text5.format(username_contact))
                    user_list6.append(user5)
                    user_list5.remove(user5)

            for user4 in user_list4:
                status = (cheack_status(user4))[0]
                if status == 1:
                    username_contact = user_1
                else:
                    username_contact = user02349
                if status != 9:
                    await bot.send_photo(user4, photo=text.dayly_photo_id4, caption=text.dayly_text4.format(username_contact))
                    user_list5.append(user4)
                    user_list4.remove(user4)

            for user3 in user_list3:
                status = (cheack_status(user3))[0]
                if status == 1:
                    username_contact = user_1
                else:
                    username_contact = user02349
                if status != 9:
                    await bot.send_photo(user3, photo=text.dayly_photo_id3, caption=text.dayly_text3.format(username_contact))
                    user_list4.append(user3)
                    user_list3.remove(user3)

            for user2 in user_list2:
                status = (cheack_status(user2))[0]
                if status == 1:
                    username_contact = user_1
                else:
                    username_contact = user02349
                if status != 9:
                    await bot.send_message(user2, text=text.dayly_text2.format(username_contact))
                    user_list3.append(user2)
                    user_list2.remove(user2)

            for user1 in user_list1:
                status = (cheack_status(user1))[0]
                if status == 1:
                    username_contact = user_1
                else:
                    username_contact = user02349
                if status != 9:
                    await bot.send_photo(user1, photo=text.dayly_photo_id1, caption=text.dayly_text1.format(username_contact))
                    user_list2.append(user1)
                    user_list1.remove(user1)

        await asyncio.sleep(3600)

async def shutdown(dispatcher: Dispatcher):
    await dispatcher.storage.close()
    await dispatcher.storage.wait_closed()

@db.callback_query_handler(text='otemena',state='*')
async def otmena_12(call: types.callback_query, state: FSMContext):
    await bot.send_message(call.message.chat.id, 'Отменено')
    await state.finish()
    try:
        await bot.delete_message(call.message.chat.id,message_id=call.message.message_id)
    except: pass

@db.message_handler(state=st_reg.step_q,content_types=['text','photo','video','video_note','animation','voice','sticker']) # Предосмотр поста
async def redarkt_post(message: types.Message, state: FSMContext):
    await st_reg.st_name.set()
    murkap = types.InlineKeyboardMarkup()
    bat0 = types.InlineKeyboardButton(text='ОТМЕНА', callback_data='otemena')
    bat1 = types.InlineKeyboardButton(text='РАЗОСЛАТЬ', callback_data='send_ras')
    bat2 = types.InlineKeyboardButton(text='Добавить кнопки', callback_data='add_but')
    murkap.add(bat1)
    murkap.add(bat2)
    murkap.add(bat0)

    await message.copy_to(chat_id=message.chat.id)
    q = message
    await state.update_data(q=q)

    await bot.send_message(chat_id=message.chat.id,text='Пост сейчас выглядит так 👆',reply_markup=murkap)

# НАСТРОЙКА КНОПОК
@db.callback_query_handler(text='add_but',state=st_reg.st_name) # Добавление кнопок
async def addbutton(call: types.callback_query, state: FSMContext):
    await bot.delete_message(chat_id=call.message.chat.id,message_id=call.message.message_id)
    await bot.send_message(call.message.chat.id,text='Отправляй мне кнопки по принципу Controller Bot\n\n'
                                                     'Пока можно добавить только одну кнопку')
    await st_reg.step_regbutton.set()

@db.message_handler(state=st_reg.step_regbutton,content_types=['text']) # Текст кнопок в неформате
async def redarkt_button(message: types.Message, state: FSMContext):
    arr2 = message.text.split('-')

    k = -1  # Убираем пробелы из кнопок
    for i in arr2:
        k+=1
        if i[0] == ' ':
            if i[-1] == ' ':
                arr2[k] = (i[1:-1])
            else:
                arr2[k] = (i[1:])

        else:
            if i[-1] == ' ':

                arr2[0] = (i[:-1])
            else:
                pass

    # arr2 - Массив с данными

    try:
        murkap = types.InlineKeyboardMarkup() #Клавиатура с кнопками
        bat = types.InlineKeyboardButton(text= arr2[0], url=arr2[1])
        murkap.add(bat)

        data = await state.get_data()
        mess = data['q']  # ID сообщения для рассылки

        await bot.copy_message(chat_id=message.chat.id, from_chat_id=message.chat.id,message_id=mess.message_id,reply_markup=murkap)

        await state.update_data(text_but =arr2[0]) # Обновление Сета
        await state.update_data(url_but=arr2[1])  # Обновление Сета

        murkap2 = types.InlineKeyboardMarkup() # Клавиатура - меню
        bat0 = types.InlineKeyboardButton(text='ОТМЕНА', callback_data='otemena')
        bat1 = types.InlineKeyboardButton(text='РАЗОСЛАТЬ', callback_data='send_ras')
        murkap2.add(bat1)
        murkap2.add(bat0)

        await bot.send_message(chat_id=message.chat.id,text='Теперь твой пост выглядит так☝',reply_markup=murkap2)

    except:
        await bot.send_message(chat_id=message.chat.id,text='Ошибка. Отменено')
        await state.finish()

# КОНЕЦ НАСТРОЙКИ КНОПОК

@db.callback_query_handler(text='send_ras',state="*") # Рассылка
async def fname_step(call: types.callback_query, state: FSMContext):
    await bot.delete_message(chat_id=call.message.chat.id,message_id=call.message.message_id)

    data = await state.get_data()
    mess = data['q'] # Сообщения для рассылки

    type_rass = data['type_rassilki']
    murkap = types.InlineKeyboardMarkup()  # Клавиатура с кнопками

    try: #Пытаемся добавить кнопки. Если их нету оставляем клаву пустой
        text_but = data['text_but']
        url_but = data['url_but']
        bat = types.InlineKeyboardButton(text=text_but, url=url_but)
        murkap.add(bat)
    except: pass

    db = sqlite3.connect('server.db')
    sql = db.cursor()
    await state.finish()
    if type_rass == 1:
        users = sql.execute(f"SELECT id FROM user_time WHERE status_active = 1").fetchall()
    else:
        users = sql.execute(f"SELECT id FROM user_time WHERE status_active = 0 or status_active = 2 or status_active = 3 or status_active =4").fetchall()

    bad = 0
    good = 0
    await bot.send_message(call.message.chat.id, f"<b>Всего пользователей: <code>{len(users)}</code></b>\n\n<b>Расслыка начата!</b>",
                           parse_mode="html")
    for i in users:
        await asyncio.sleep(1)
        try:
            await mess.copy_to(i[0],reply_markup=murkap)
            good += 1
        except:
            bad += 1

    await bot.send_message(
        call.message.chat.id,
        "<u>Рассылка окончена\n\n</u>"
        f"<b>Всего пользователей:</b> <code>{len(users)}</code>\n"
        f"<b>Отправлено:</b> <code>{good}</code>\n"
        f"<b>Не удалось отправить:</b> <code>{bad}</code>",
        parse_mode="html"
    )
#########################################################

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.create_task(send_to_a_certain_hour())
    executor.start_polling(db, on_shutdown=shutdown,skip_updates=True)


import setuptools

with open("README.md", "r", encoding="utf-8") as fh:
    long_description = fh.read()

setuptools.setup(
    name='wutools',
    version='0.0.3',
    author='Jason Yunger',
    author_email='jason.yunger@gmail.com',
    description='Testing installation of Package',
    long_description=long_description,
    long_description_content_type="text/markdown",
    url='https://github.com/jyunger/wutest',
    project_urls = {
        "Bug Tracker": "https://github.com/jyunger/wutest/issues"
    },
    license='MIT',
    packages=setuptools.find_packages(),
    install_requires=['numpy', 'pandas', 'psutil', 'pyathena', 'graphviz', 'sqlalchemy', 'sqlparse'],
)


import argparse
import scipy
from scipy import ndimage
import cv2
import numpy as np
import sys
import json

import torch
from torch.autograd import Variable
import torchvision.models as models
import torch.nn.functional as F
import torch.backends.cudnn as cudnn
from torch.utils import data
# from networks.unet2D import UNet
from networks.efficient import EfficientSegBackbone
from dataset.MyoPSDataset import MyoPSDataSet, MyoPSDataSetVal
from collections import OrderedDict
import os
import scipy.ndimage as nd
from math import ceil
from PIL import Image as PILImage
import nibabel as nib
from utils.ParaFlop import print_model_parm_nums, print_model_parm_flops, torch_summarize_df
import matplotlib.pyplot as plt
# from utils.encoding import DataParallelModel, DataParallelCriterion
import torch.nn as nn
from engine import Engine

def get_arguments():
    """Parse all the arguments provided from the CLI.

    Returns:
      A list of parsed arguments.
    """
    parser = argparse.ArgumentParser(description="W-like Network for 3D Medical Image Segmentation.")

    # paths
    parser.add_argument("--data_dir", type=str, default='dataset/')
    parser.add_argument("--val_list", type=str, default='list/MyoPS2020/val5f_5.txt')
    parser.add_argument("--output_path", type=str, default='output/MyoPS2020/tmp/')
    parser.add_argument("--restore_from", type=str, default='snapshots/MyoPS2020/all_r1_EB3_4GPU_bs32_FP16/MyoPS2020_all_r1_EB3_4GPU_bs32_FP16_final.pth')

    # training details
    parser.add_argument("--input_size", type=str, default='288,288')
    parser.add_argument("--batch_size", type=int, default=4)
    parser.add_argument("--num_gpus", type=int, default=1)
    parser.add_argument('--local_rank', type=int, default=0)
    parser.add_argument("--FP16", type=bool, default=False)
    parser.add_argument("--num_epochs", type=int, default=500)
    parser.add_argument("--patience", type=int, default=3)
    parser.add_argument("--start_epoch", type=int, default=0)
    parser.add_argument("--save_pred_every", type=int, default=10)
    parser.add_argument("--learning_rate", type=float, default=1e-3)
    parser.add_argument("--num_classes", type=int, default=5 + 1)
    parser.add_argument("--compound_coef", type=int, default=3)  # B0-B7
    parser.add_argument("--num_workers", type=int, default=4)

    parser.add_argument("--weight_std", type=bool, default=True)
    parser.add_argument("--momentum", type=float, default=0.9)
    parser.add_argument("--power", type=float, default=0.9)
    parser.add_argument("--weight_decay", type=float, default=0.0005)

    parser.add_argument("--ignore_label", type=int, default=255)
    parser.add_argument("--is_training", action="store_true")
    parser.add_argument("--not_restore_last", action="store_true")
    parser.add_argument("--save_num_images", type=int, default=2)

    # data aug.
    parser.add_argument("--random_mirror", type=bool, default=True, )
    parser.add_argument("--random_scale", type=bool, default=True)
    parser.add_argument("--random_seed", type=int, default=1234)

    # others
    parser.add_argument("--gpu", type=str, default='None')
    parser.add_argument("--recurrence", type=int, default=1)
    parser.add_argument("--ft", type=bool, default=False)

    return parser

def get_palette(num_cls):
    """ Returns the color map for visualizing the segmentation mask.
    Args:
        num_cls: Number of classes
    Returns:
        The color map
    """

    n = num_cls
    palette = [0] * (n * 3)
    for j in range(0, n):
        lab = j
        palette[j * 3 + 0] = 0
        palette[j * 3 + 1] = 0
        palette[j * 3 + 2] = 0
        i = 0
        while lab:
            palette[j * 3 + 0] |= (((lab >> 0) & 1) << (7 - i))
            palette[j * 3 + 1] |= (((lab >> 1) & 1) << (7 - i))
            palette[j * 3 + 2] |= (((lab >> 2) & 1) << (7 - i))
            i += 1
            lab >>= 3
    return palette

def pad_image(img, target_size):
    """Pad an image up to the target size."""
    deps_missing = target_size[0] - img.shape[2]
    rows_missing = target_size[1] - img.shape[3]
    cols_missing = target_size[2] - img.shape[4]
    padded_img = np.pad(img, ((0, 0), (0, 0),(0, deps_missing), (0, rows_missing), (0, cols_missing)), 'constant')
    return padded_img

def multi_net(net_list, img):
    img = torch.from_numpy(img).cuda()
    padded_prediction = net_list[0](img)
    padded_prediction = torch.softmax(padded_prediction, 1)

    for i in range(1, len(net_list)):
        padded_prediction_i = net_list[i](img)
        padded_prediction_i = torch.softmax(padded_prediction_i, 1)
        padded_prediction += padded_prediction_i
    padded_prediction /= len(net_list)
    return padded_prediction.cpu().numpy()

# for 2D
def predict_sliding(net, image, tile_size, classes):  # image: 1,3,5,256,256, tile_size:256x256
    image_size = image.shape
    overlap = 1 / 3

    strideHW = ceil(tile_size[0] * (1 - overlap))
    tile_rows = int(ceil((image_size[3] - tile_size[0]) / strideHW) + 1)  # strided convolution formula
    tile_cols = int(ceil((image_size[4] - tile_size[1]) / strideHW) + 1)
    # print("Need %i x %i x %i prediction tiles @ stride %i x %i px" % (tile_deps, tile_cols, tile_rows, strideD, strideHW))
    full_probs = np.zeros((image_size[0], classes, image_size[2], image_size[3], image_size[4])).astype(np.float32)  # 1x4x155x240x240
    count_predictions = np.zeros((image_size[0], classes, image_size[2], image_size[3], image_size[4])).astype(np.float32)
    full_probs = torch.from_numpy(full_probs).cuda()
    count_predictions = torch.from_numpy(count_predictions).cuda()
    tile_counter = 0

    for dep in range(image_size[2]):
        for row in range(tile_rows):
            for col in range(tile_cols):
                x1 = int(col * strideHW)
                y1 = int(row * strideHW)
                x2 = min(x1 + tile_size[1], image_size[4])
                y2 = min(y1 + tile_size[0], image_size[3])
                x1 = max(int(x2 - tile_size[1]), 0)  # for portrait images the x1 underflows sometimes
                y1 = max(int(y2 - tile_size[0]), 0)  # for very few rows y1 underflows
                d1 = dep
                d2 = dep+1

                img = torch.squeeze(image[:, :, d1:d2, y1:y2, x1:x2], 2)
                img = img.numpy()

                tile_counter += 1
                prediction1 = multi_net([net], img)
                prediction2 = multi_net([net], img[:, :, :, ::-1].copy())[:, :, :, ::-1]
                prediction3 = multi_net([net], img[:, :, ::-1, :].copy())[:, :, ::-1, :]
                prediction = (prediction1 + prediction2 + prediction3) / 3.

                prediction = torch.unsqueeze(torch.from_numpy(prediction).cuda(), 2)

                if isinstance(prediction, list):
                    shape = np.array(prediction[0].shape)
                    shape[0] = prediction[0].shape[0] * len(prediction)
                    shape = tuple(shape)
                    preds = torch.zeros(shape).cuda()
                    bs_singlegpu = prediction[0].shape[0]
                    for i in range(len(prediction)):
                        preds[i * bs_singlegpu: (i + 1) * bs_singlegpu] = prediction[i]
                    count_predictions[:, :, d1:d2, y1:y2, x1:x2] += 1
                    full_probs[:, :, d1:d2, y1:y2, x1:x2] += preds

                else:
                    count_predictions[:, :, d1:d2, y1:y2, x1:x2] += 1
                    full_probs[:, :, d1:d2, y1:y2, x1:x2] += prediction

    # average the predictions in the overlapping regions
    full_probs /= count_predictions
    return full_probs.cpu().data.numpy()

def get_confusion_matrix(gt_label, pred_label, class_num):
        """
        Calcute the confusion matrix by given label and pred
        :param gt_label: the ground truth label
        :param pred_label: the pred label
        :param class_num: the nunber of class
        :return: the confusion matrix
        """
        index = (gt_label * class_num + pred_label).astype('int32')
        label_count = np.bincount(index)
        confusion_matrix = np.zeros((class_num, class_num))

        for i_label in range(class_num):
            for i_pred_label in range(class_num):
                cur_index = i_label * class_num + i_pred_label
                if cur_index < len(label_count):
                    confusion_matrix[i_label, i_pred_label] = label_count[cur_index]

        return confusion_matrix

def dice_score(preds, labels):
    assert preds.shape[0] == labels.shape[0], "predict & target batch size don't match"
    predict = preds.view().reshape(preds.shape[0], -1)
    target = labels.view().reshape(labels.shape[0], -1)

    num = np.sum(np.multiply(predict, target), axis=1)
    den = np.sum(predict, axis=1) + np.sum(target, axis=1) +1

    dice = 2*num / den

    return dice.mean()

def main():
    """Create the model and start the evaluation process."""
    parser= get_arguments()
    #os.environ["CUDA_VISIBLE_DEVICES"] = '0'

    with Engine(custom_parser=parser) as engine:
        args = parser.parse_args()
        torch.cuda.set_device(args.local_rank)

        h, w = map(int, args.input_size.split(','))
        input_size = (h, w)

        cudnn.benchmark = True
        seed = args.random_seed
        if engine.distributed:
            seed = args.local_rank
        torch.manual_seed(seed)
        if torch.cuda.is_available():
            torch.cuda.manual_seed(seed)

        model = EfficientSegBackbone(num_classes=args.num_classes, compound_coef=args.compound_coef, load_weights=True)
        print_model_parm_nums(model)

        # print_model_parm_flops(model)
        # model = nn.DataParallel(model)

        print('loading from checkpoint: {}'.format(args.restore_from))
        if os.path.exists(args.restore_from):
            model.load_state_dict(torch.load(args.restore_from, map_location=torch.device('cpu')))
            #model.load_state_dict(torch.load(args.restore_from, map_location=torch.device(args.local_rank)))
        else:
            print('File not exists in the reload path: {}'.format(args.restore_from))

        model.eval()
        model.cuda()

        testloader = data.DataLoader(
            MyoPSDataSetVal(args.data_dir, args.val_list),
            batch_size=1, shuffle=False, pin_memory=True)

        if not os.path.exists(args.output_path):
            os.makedirs(args.output_path)

        dice_LV = 0
        dice_RV = 0
        dice_MY = 0
        dice_edema = 0
        dice_scars = 0

        for index, batch in enumerate(testloader):
            # print('%d processd'%(index))
            image, label, name, affine = batch
            affine = affine[0].numpy()
            with torch.no_grad():
                output = predict_sliding(model, image, input_size, args.num_classes)

            seg_pred = np.asarray(np.argmax(output, axis=1), dtype=np.uint8)
            seg_pred = np.where(seg_pred == 1, 500, seg_pred)
            seg_pred = np.where(seg_pred == 2, 600, seg_pred)
            seg_pred = np.where(seg_pred == 3, 200, seg_pred)
            seg_pred = np.where(seg_pred == 4, 1220, seg_pred)
            seg_pred = np.where(seg_pred == 5, 2221, seg_pred)

            seg_pred_background = (seg_pred == 0)
            seg_pred_LV = (seg_pred == 500)
            seg_pred_RV = (seg_pred == 600)
            seg_pred_MY = (seg_pred == 200)
            seg_pred_edema = (seg_pred == 1220)
            seg_pred_scars = (seg_pred == 2221)

            seg_gt = np.asarray(np.argmax(label.cpu().numpy(), axis=1), dtype=np.uint8)
            seg_gt = np.where(seg_gt == 1, 500, seg_gt)
            seg_gt = np.where(seg_gt == 2, 600, seg_gt)
            seg_gt = np.where(seg_gt == 3, 200, seg_gt)
            seg_gt = np.where(seg_gt == 4, 1220, seg_gt)
            seg_gt = np.where(seg_gt == 5, 2221, seg_gt)

            seg_gt_background = (seg_gt == 0)
            seg_gt_LV = (seg_gt == 500)
            seg_gt_RV = (seg_gt == 600)
            seg_gt_MY = (seg_gt == 200)
            seg_gt_edema = (seg_gt == 1220)
            seg_gt_scars = (seg_gt == 2221)

            dice_LV_i = dice_score(seg_pred_LV, seg_gt_LV)
            dice_RV_i = dice_score(seg_pred_RV, seg_gt_RV)
            dice_MY_i = dice_score(seg_pred_MY, seg_gt_MY)
            dice_edema_i = dice_score(seg_pred_edema, seg_gt_edema)
            dice_scars_i = dice_score(seg_pred_scars, seg_gt_scars)
            print('Processing {}: LV = {:.4}, RV = {:.4}, MY = {:.4}, edema = {:.4}, scars = {:.4}'.format(name, dice_LV_i, dice_RV_i, dice_MY_i, dice_edema_i, dice_scars_i))

            dice_LV += dice_LV_i
            dice_RV += dice_RV_i
            dice_MY += dice_MY_i
            dice_edema += dice_edema_i
            dice_scars += dice_scars_i

            seg_pred = seg_pred[0].transpose((1,2,0))   #240x240x155
            seg_gt = seg_gt[0].transpose((1,2,0))

            seg_pred = nib.Nifti1Image(seg_pred, affine=affine)
            seg_gt = nib.Nifti1Image(seg_gt, affine=affine)
            # seg_name = name[0].replace("volume", "segmentation")
            seg_name = name[0]
            seg_save_p = os.path.join(args.output_path+'/%s.nii.gz' % (seg_name))
            gt_save_p = os.path.join(args.output_path + '/%s_gt.nii.gz' % (seg_name))
            nib.save(seg_pred, seg_save_p)
            nib.save(seg_gt, gt_save_p)

        dice_LV_avg = dice_LV / (index + 1)
        dice_RV_avg = dice_RV / (index + 1)
        dice_MY_avg = dice_MY / (index + 1)
        dice_edema_avg = dice_edema / (index + 1)
        dice_scanrs_avg = dice_scars / (index + 1)
        print('Average score: LV = {:.4}, RV = {:.4}, MY = {:.4}, edema = {:.4}, scars = {:.4}'.format(dice_LV_avg, dice_RV_avg, dice_MY_avg, dice_edema_avg, dice_scanrs_avg))

if __name__ == '__main__':
    main()


#!/usr/bin/env python3
import sys
sys.setrecursionlimit(10**6)
INF = 10 ** 9 + 1  # sys.maxsize # float("inf")
MOD = 10 ** 9 + 7

def debug(*x):
    print(*x, file=sys.stderr)

def solve(SOLVE_PARAMS):
    pass

def main():
    N, M = map(int, input().split())
    is_head = [True] * N
    from collections import defaultdict
    edges = defaultdict(list)
    for q in range(M):
        a, b = map(int, input().split())
        a -= 1
        b -= 1
        is_head[b] = False
        edges[a].append(b)

    to_tail = [-1] * N
    visited = [False] * N

    def dfs(x):
        buf = [0]
        visited[x] = True
        for v in edges[x]:
            if visited[v]:
                continue
            ret = to_tail[v]
            if ret == -1:
                ret = dfs(v)
                to_tail[v] = ret
            buf.append(ret)
        return max(buf) + 1

    buf = [1]
    for i in range(N):
        visited = [False] * N
        buf.append(dfs(i))

    # debug(": to_tail", to_tail)
    print(max(buf))

# tests
T1 = """
5 3
1 2
3 4
5 1
"""
TEST_T1 = """
>>> as_input(T1)
>>> main()
3
"""

T2 = """
4 10
1 2
2 1
1 2
2 1
1 2
1 3
1 4
2 3
2 4
3 4
"""
TEST_T2 = """
>>> as_input(T2)
>>> main()
4
"""

T3 = """
10 4
3 1
4 1
5 9
2 6
"""
TEST_T3 = """
>>> as_input(T3)
>>> main()
3
"""

def _test():
    import doctest
    doctest.testmod()
    g = globals()
    for k in sorted(g):
        if k.startswith("TEST_"):
            doctest.run_docstring_examples(g[k], g, name=k)

def as_input(s):
    "use in test, use given string as input file"
    import io
    f = io.StringIO(s.strip())
    g = globals()
    g["input"] = lambda: bytes(f.readline(), "ascii")
    g["read"] = lambda: bytes(f.read(), "ascii")

input = sys.stdin.buffer.readline
read = sys.stdin.buffer.read

if sys.argv[-1] == "-t":
    print("testing")
    _test()
    sys.exit()

main()


from django.shortcuts import get_object_or_404
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status

from .models import Client, Mailing, Message
from .serializers import MailingSerializer, ClientSerializer, MailingMessagesSerializer
from .service import check_mailing
from .tasks import send_message

from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema

response_400 = openapi.Response('BAD_REQUEST')
client_response_get = openapi.Response('Client list', ClientSerializer(many=True))
client_response_post = openapi.Response('New Client', ClientSerializer)
client_response_detail_get = openapi.Response('Client object', ClientSerializer)
mailing_response_get = openapi.Response('Mailing list', MailingSerializer(many=True))
mailing_response_post = openapi.Response('New Mailing', MailingSerializer)
mailing_response_detail_get = openapi.Response('Mailing object', MailingSerializer)
mailing_statistics_response_get = openapi.Response('New Mailing', MailingMessagesSerializer(many=True))

@swagger_auto_schema(method='get', responses={200: client_response_get})
@swagger_auto_schema(method='post', request_body=ClientSerializer)
@api_view(['GET', 'POST'])
def api_client(request):
    if request.method == 'GET':
        clients = Client.objects.all()
        serializer = ClientSerializer(clients, many=True)
        return Response(serializer.data)
    if request.method == 'POST':
        serializer = ClientSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@swagger_auto_schema(method='get', responses={200: client_response_detail_get})
@swagger_auto_schema(methods=['put', 'patch'], request_body=ClientSerializer)
@api_view(['GET', 'PUT', 'PATCH', 'DELETE'])
def api_client_detail(request, pk):
    client = get_object_or_404(Client, pk=pk)
    if request.method == 'GET':
        serializer = ClientSerializer(client)
        return Response(serializer.data)
    elif request.method == 'PUT' or request.method == 'PATCH':
        serializer = ClientSerializer(client, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    elif request.method == 'DELETE':
        client.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

@swagger_auto_schema(method='get', responses={200: mailing_response_get})
@swagger_auto_schema(method='post', request_body=MailingSerializer)
@api_view(['GET', 'POST'])
def api_mailing(request):
    if request.method == 'GET':
        mailing = Mailing.objects.all()
        serializer = MailingSerializer(mailing, many=True)
        return Response(serializer.data)
    if request.method == 'POST':
        serializer = MailingSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            check_mailing(serializer.data['id'])
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

@swagger_auto_schema(method='get', responses={200: mailing_response_detail_get})
@swagger_auto_schema(methods=['put', 'patch'], request_body=MailingSerializer)
@api_view(['GET', 'PUT', 'PATCH', 'DELETE'])
def api_mailing_detail(request, pk):
    mailing = get_object_or_404(Mailing, pk=pk)
    if request.method == 'GET':
        return Response(MailingMessagesSerializer(mailing).data)
    elif request.method == 'PUT' or request.method == 'PATCH':
        serializer = MailingSerializer(mailing, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    elif request.method == 'DELETE':
        mailing.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

@swagger_auto_schema(method='get', responses={200: mailing_statistics_response_get})
@api_view(['GET'])
def api_mailing_statistics(request):
    context = []
    mailings = Mailing.objects.all()

    for mailing in mailings:
        context.append(MailingMessagesSerializer(instance=mailing).data)

    return Response(context)

@api_view(['GET'])
def api_test(request):
    if request.method == 'GET':
        mailing = Mailing.objects.get(pk=10)
        clients = mailing.get_clients()
        serializer = ClientSerializer(clients, many=True)
        return Response(serializer.data)

@api_view(['GET'])
def api_send_created_messages(request):
    messages = Message.objects.filter(status=Message.Status.CREATED)
    for i in messages:
        send_message.delay(i.id,)
    return Response([], status=status.HTTP_200_OK)


#!/usr/bin/env python3
"""Program for testing constrained sequence alignm"""
import subprocess
from pprint import pprint
import json
import argparse
import sys
import string
import random
import datetime
from constrain_align import run_blast

AMINO_ACIDS = "GAVLIPFYWSTCMNQKRHDE"

NUM_PRINT = 50

def main():
    """Main function"""
    args = parse_arguments()
    if (args.random is None):
        seqs = args.specific
    elif (args.specific is None):
        seqs = args.random
    elif (args.random is None and args.specific is None):
        raise ValueError("Please use either -r or -s")
    else:
        raise ValueError("Pleae only use one of -r or -s")
    weights = args.w or [random.randrange(1,20) for _ in seqs]
    if weights and len(weights) != len(seqs):
        raise ValueError('Number of weights and number of sequences must be of same length')
    aminos = args.aminos
    if aminos:
        if not all(x in AMINO_ACIDS for x in aminos):
            raise ValueError('One of your amino acids is funny. Please choose amino acids from "{}"'.format(AMINO_ACIDS))
    outfile = open(args.out, 'w') if args.out else sys.stdout
    if (args.random):
        test_seqs = [make_seqs(s, amino_acids=aminos)for s in seqs]
    else:
        test_seqs = seqs
    print('Sequences are:', file=outfile)
    print(test_seqs, file=outfile)
    combined_seq = ""
    for x in test_seqs:
        combined_seq += x
    print("Combined sequence for BLAST:", file=outfile)
    print(combined_seq + '\n',file=outfile)

    #Only print top NUM_PRINT results
    blast_items = run_blast(combined_seq)
    print('The blast says:', file=outfile)
    bresults = len(blast_items)
    #if NUM_PRINT < bresults:
    #   bresults = NUM_PRINT
    if len(blast_items) > 0:
        [print(blast_items[x], file=outfile) for x in range(0, bresults)]
    #prints all blast results
    #[print(x, file=outfile) for x in blast_items]

    # Only print top NUM_PRINT results
    #want top 10 distinct scored
    our_program = subprocess.run(['python3', 'constrain_align.py', '-s'] + [x + ':{}'.format(w) for x, w in zip(test_seqs, weights)], stdout=subprocess.PIPE)
    print('\nOur program says:', file=outfile)
    our_items = our_program.stdout.decode('utf-8').split('\n')
    oresults = int(len(our_items)/4)
    #if NUM_PRINT < oresults:
    #    oresults = NUM_PRINT
    if len(our_items) > 0:
        idx = 0
        limit = oresults*4
        while idx < limit:
            print(our_items[idx], file=outfile)
            idx += 4
    #prints all our programs results
    #[print(x, file=outfile) for x in our_program.stdout.decode('utf-8').split('\n')]
    print('-'*80, file=outfile)

def make_seqs (seq_len, amino_acids=None):
    amino_acids = amino_acids or AMINO_ACIDS
    return ''.join(random.choice(amino_acids) for x in range(seq_len))

def parse_arguments():
    """Parse command line arguments to the program"""
    parser = argparse.ArgumentParser()
    parser.add_argument('-s', "--specific", help="Specify a specific amino acid sequence to test", nargs="*", default=None)
    parser.add_argument('-r',
        "--random", help="Specify the length of random sequnece you want to test", nargs='*', type=int, default=None)
    parser.add_argument('-w', "-weight",
                        help="Specify the weight you want to use for the constrained alignment", nargs='*', type=int, default=None)
    parser.add_argument('-o', '--out', default=None,
                        help='Specify output filename.')
    parser.add_argument('-a', '--aminos', default=None, type=str,
                        help='Specify amino acids.')
    args = parser.parse_args()
    return args

if __name__ == '__main__':
    main()


from django.urls import path
from cart.views import cart_add, cart_remove, cart_details, cart_clear, cart_update

urlpatterns = [
    path('cart_details/', cart_details, name='cart_details'),
    path('cart_add/', cart_add, name='cart_add'),
    path('cart_update/', cart_update, name='cart_update'),
    path('cart_remove/', cart_remove, name='cart_remove'),
    path('cart_clear/', cart_clear, name='cart_clear'),

]


#-*- coding: utf-8 -*-
u"""

.. moduleauthor:: Martí Congost <marti.congost@whads.com>
"""
import cherrypy
from cocktail.pkgutils import resolve
from woost.controllers.basecmscontroller import BaseCMSController
from woost.extensions.payments.paymentgateway import PaymentGateway

class PaymentRootController(BaseCMSController):
    """Root controller for all payment related requests.

    This controller does nothing by itself, it merely identifies the payment
    gateway that should handle an incomming request and forwards the request to
    the gateway's controller (an instance of L{PaymentGatewayController}).
    """

    def resolve(self, path):

        if not path:
            raise cherrypy.NotFound()

        # Identify the gateway involved in the payment
        gateway_id = path.pop(0)

        try:
            gateway_id = int(gateway_id)
        except:
            raise cherrypy.HTTPError(400)

        gateway = PaymentGateway.get_instance(gateway_id)

        if gateway is None:
            raise cherrypy.NotFound()

        # Forward the request to the gateway's controller
        controller_class = resolve(gateway.payment_gateway_controller_class)
        return controller_class(gateway)


import raw_read
import subprocess as sp
from matplotlib import pyplot
import numpy as np
from files import *
from sklearn.metrics import mean_squared_error

[arrs1,plots]=raw_read.rawread('output/rawfile.raw')
# time
stime = arrs1[0]
res_out = arrs1[1:-1]
x=res_out.T
temp = np.linalg.pinv(x)
vref=np.load("output/ref.npy")
vref=vref.T
w_out = np.load("output/w_out.npy")
outlayer=1

readout=np.zeros((res_out.shape[1],outlayer))
for t in range(0, res_out.shape[1]):
     # readout[t]=np.dot(res[:,:,t],w_out)
    readout[t] = np.dot(res_out[:, t], w_out)

# error = abs(readout - vref)
error = abs(readout[1:] - vref[1:])
error1= mean_squared_error(readout[1:], vref[1:],squared=False)

print(error1)

pyplot.figure(figsize=(10,6))
pyplot.subplots_adjust(wspace =0, hspace =0.2)
pyplot.plot(stime[1:],vref[1:],'r')
pyplot.plot(stime[1:],readout[1:],'mediumspringgreen')

pyplot.xlabel("Time (s)",fontsize=15)
pyplot.show()

###################################plot########################################
# stime = arrs1[0]
# current = arrs1[1:19]
# memstate=arrs1[21:39]
#
# current1=arrs1[1]
# state1=arrs1[21]
#
#
# pyplot.figure(figsize=(10,3))
# pyplot.subplots_adjust(wspace =0, hspace =0.2)
# # pyplot.plot(stime[1:],current1[1:],'r')
# pyplot.plot(stime[1:],state1[1:],'mediumspringgreen')
#
# pyplot.xlabel("Time (s)",fontsize=15)
# pyplot.show()
#
# pyplot.figure(figsize=(10,3))
# pyplot.subplots_adjust(wspace =0, hspace =0.2)
# pyplot.plot(stime[1:],current1[1:],'r')
# # pyplot.plot(stime[1:],state1[1:],'mediumspringgreen')
# pyplot.xlabel("Time (s)",fontsize=15)
# pyplot.show()


import sqlite3

def create_table():
        sqlstr = "create table user (sid int(5) primary key, \
        name varchar(10), email varchar(25))"
        conn.execute(sqlstr)
        print("create table successfully")
        conn.close()

def initiate_table():
        cur = conn.cursor()
        sqlstr1 = "insert into user(sid, name, email) values(1001, '张大山', 'zhangds@163.com') "
        cur.execute(sqlstr1)
        sqlstr2 = "insert into user(sid, name, email) values(1002, '李晓丽', 'lixli@163.com') "
        cur.execute(sqlstr2)
        sqlstr3 = "insert into user(sid, name, email) values(1003, '赵四方', 'zaoshi@163.com') "
        cur.execute(sqlstr3)
        conn.commit()
        print("Records created successfully")
        conn.close()
def get_data():
        cur = conn.cursor()
        sqlstr = "select * from  user"
        s = cur.execute(sqlstr)
        for row in s:   #得到的赋值给s
                print("sid=", row[0])
                print("name=", row[1])
                print("email=", row[2], '\n')
        conn.close()
def updata_data():

        cur = conn.cursor()
        sql_update = "update user set email='zhaosf@abc.com' where sid=1003"
        cur.execute(sql_update)
        conn.commit()

        sql_select = "select * from  user where sid=1003"
        s = cur.execute(sql_select)
        for row in s:
                print("sid=", row[0])
                print("name=", row[1])
                print("email=", row[2], '\n')
        conn.close()
def delete_data():
        cur = conn.cursor()
        sql_update = "delete from user  where sid=1002"
        cur.execute(sql_update)
        conn.commit()
        sql_select = "select * from  user"
        s = cur.execute(sql_select)
        for row in s:
                print("sid=", row[0])
                print("name=", row[1])
                print("email=", row[2], '\n')
        conn.close()

if __name__=="__main__":
        conn = sqlite3.connect("d:/groupdatabase.db")
        get_data()
        # conn = sqlite3.connect("d:/groupdatabase.db")
        # updata_data()
        # conn = sqlite3.connect("d:/groupdatabase.db")
        # delete_data()


import torch
from game import DataGenArena
from torch.autograd import Variable
from torch.utils.data import DataLoader
import os

# criterion = torch.nn.SmoothL1Loss()
# optimizer = torch.optim.SGD(model.parameters(), lr=0.001)

class AITrainer:
    # TODO: concurrent usage of self.model and player.network makes me nervous
    # TODO: add name? hmmm
    # also unsure about loss and optimizer params
    # TODO: remove gen parameter (?)
    def __init__(self, player, model_name=None, model_dir=None, matches=100, batch_size=8,
                 loss=torch.nn.SmoothL1Loss, optimizer=torch.optim.SGD, lr=0.001, gen=0):
        self.player = player
        self.matches = matches
        self.batch_size = batch_size
        self.epochs = 2

        self.model_dir = model_dir
        self.gen = gen
        # TODO: fix use of preexisting model
        self.model_path = model_name
        if self.model_path is not None:
            print("Hi")
            self.player.load_model(self.model_path)
            # TODO: figure out how to get gen from somewhere
            self.gen = gen
        else:
            self.gen = 0
            self.model_path = self.full_path()
            self.player.save_model(self.model_path)

        # self.model = player.network
        self.loss = loss()
        self.optimizer = optimizer(self.player.network.parameters(), lr=lr)
        self.generations()

    def generation(self):
        print(self.gen)
        path = self.full_path()
        self.player.load_model(path)
        model = self.player.network
        data = DataGenArena(self.player, matches=self.matches)
        train_loader = DataLoader(dataset=data,
                                  batch_size=self.batch_size,
                                  shuffle=True,
                                  num_workers=2)

        for epoch in range(self.epochs):
            for i, data in enumerate(train_loader, 0):
                # get the inputs
                inputs, labels = data

                # wrap them in Variable
                inputs, labels = Variable(inputs), Variable(labels)

                # Forward pass: Compute predicted y by passing x to the model
                y_pred = model(inputs.float())

                # Compute and print loss
                loss = self.loss(y_pred, labels)
                print(epoch, i, loss.data.item())

                # Zero gradients, perform a backward pass, and update the weights.
                self.optimizer.zero_grad()
                loss.backward()
                self.optimizer.step()

        self.gen += 1

        path = self.full_path()
        model.save_model(path)

    def generations(self):
        while True:
            self.generation()

    def full_path(self):
        # if not os.path.exists(file_path):
        #     os.makedirs(file_path)
        # TODO: implement player __repr__?
        file_name = f'{self.player.name}{self.player.shape}_gen{self.gen}.pt'
        if self.model_dir is not None:
            path = os.path.join(self.model_dir, file_name)
        else:
            path = file_name
        return path

if __name__ == '__main__':
    from players.nn_ai import NNAI
    shape = 7, 7
    gen = 4
    ai = NNAI("nnai", *shape, exploration_turns=5, explore_chance=0.15)
    file_name = f'{ai.name}{ai.shape}_gen{gen}.pt'
    trainer = AITrainer(ai, model_name=file_name, gen=gen)


#!/usr/bin/env python3
#
# graph timing from timing file

import sys
import pylab
import numpy
import matplotlib.pyplot as plot
from argparse import ArgumentParser
from collections import defaultdict

time_xlabel="Time in seconds"
bytes_ylabel="GB processed"

def parse_pair(line):
    h = line[11:13]
    m = line[14:16]
    s = line[17:19]
    time = (int(h) * 60 + int(m)) * 60 + int(s)
    count = int(line[24:])
    return time, count

def read_timing(timing_file):
    time_list = list()
    total_bytes_list = list()

    with open(timing_file, 'r') as infile:
        first = True
        offset = 0
        total = 0
        for line in infile:
           time, count = parse_pair(line)
           if first:
               offset = time
               first = False
           time_list.append(time - offset)
           total += count
           total_bytes_list.append(total/1000000000.0)
    return (time_list, total_bytes_list)

def plot_timing(time_list, total_bytes_list, outfile):
    plot.plot(time_list, total_bytes_list, '-bo')
    plot.xlabel(time_xlabel)
    plot.ylabel(bytes_ylabel)
    plot.title("Bytes processed over time")
    plot.savefig(outfile)

if __name__=="__main__":
    parser = ArgumentParser(prog='plot_dots.py',
                  description='Plot timestamp progress')
    parser.add_argument('timing_file', help= 'timing file')
    args = parser.parse_args()
    timing_file = args.timing_file
    if timing_file[:7] != 'logfile':
        raise ValueError("Invalid prefix '%s'" % timing_file[:7])

    time_list, total_bytes_list = read_timing(timing_file)
    for time in time_list:
        print("time: %d\n" % time)
    for total_bytes in total_bytes_list:
        print("total bytes: %d\n" % total_bytes)
    outfile = "out_%s.png" % timing_file
    plot_timing(time_list, total_bytes_list, outfile)


import io
# For Data Lake
from hdfs import InsecureClient
# For Data Warehouse
from pyhive import hive

import pandas as pd

df_source = pd.read_csv(r'output/news.csv')
df_source['News'] = df_source['News'].str.replace(r',', '')

# Define HDFS interface
hdfs_interface = InsecureClient('http://localhost:50070')
hdfs_interface.list('/')

# Delete old data
hdfs_interface.delete('/wqd7005/raw_news', recursive=True, skip_trash=True)

# Create hdfs directories to store data
hdfs_interface.makedirs('/wqd7005')
hdfs_interface.makedirs('/wqd7005/raw_news')
hdfs_interface.list('/wqd7005')

# Write data to raw_news directory

# text buffer
s_buf = io.StringIO()
# saving a data frame to a buffer (same as with a regular file):
df_source.to_csv(s_buf, index=False, header=False)

hdfs_interface.write('/wqd7005/raw_news/000000_0',
                     data=s_buf.getvalue(),
                     overwrite=True,
                     encoding = 'utf-8')

# Check if file has been written correctly
with hdfs_interface.read('/wqd7005/raw_news/000000_0', length=1024) as reader:
  content = reader.read()
content

# Create Hive Cursor
host_name = "localhost"
port = 10000
conn = hive.Connection(host=host_name, port=port, auth='NOSASL')
cur = conn.cursor()

# DATE

# Create External table for raw_news
cur.execute("DROP TABLE IF EXISTS raw_news")
cur.execute("CREATE EXTERNAL TABLE IF NOT EXISTS \
            raw_news (tdate STRING, \
                    news STRING) \
            ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' \
            STORED AS TEXTFILE LOCATION '/wqd7005/raw_news'")

# Check if warehousing successful:
cur.execute("SELECT * FROM raw_news LIMIT 10")
check=cur.fetchall()
df_check=pd.DataFrame(data=check)


# Licensed under a MIT style license - see LICENSE.txt

"""MUSE-PHANGS plotting routines
"""

__authors__   = "Eric Emsellem"
__copyright__ = "(c) 2017, ESO + CRAL"
__license__   = "MIT License"
__contact__   = " <eric.emsellem@eso.org>"

# This module provides some functions to plot and check the data reduction
#
# Eric Emsellem adapted a March 2018 version, provided by Rebecca
# and adapted it to the pymusepipe package

# Importing modules
import numpy as np

# Standard modules
from os.path import join as joinpath

# Plotting routines
import matplotlib.pyplot as plt
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.gridspec as gridspec

from .mpdaf_pipe import MuseSetImages, MuseSetSpectra
from .util_image import my_linear_model, get_flux_range

__version__ = '0.0.1 (23 March 2018)'

############################################################
#                      BEGIN
# The following parameters can be adjusted for the need of
# the specific pipeline to be used
############################################################

############################################################
#                      END
############################################################
PLOT = '\033[1;35;20m'
ENDC = '\033[0m'

def print_fig(text) :
    print(PLOT + "# GraphPipeInfo " + ENDC + text)

def open_new_wcs_figure(nfig, mywcs=None):
    """Open a new figure (with number nfig) with given wcs.
    If not WCS is provided, just opens a subplot in that figure.

    Input
    -----
    nfig : int
        Figure number to consider
    mywcs : astropy.wcs.WCS
        Input WCS to open a new figure (Default value = None)

    Returns
    -------
    fig, subplot
        Figure itself with the subplots using the wcs projection

    """

    # get the figure
    fig = plt.figure(nfig)

    # Clean the figure
    plt.clf()

    # Adding axes with WCS
    if mywcs is None:
        return fig, fig.add_subplot(1, 1, 1)
    else:
        return fig, fig.add_subplot(1, 1, 1, projection=mywcs)

def plot_compare_contours(data1, data2, plotwcs=None, labels=('Data1', 'Data2'), levels=None,
                          nlevels=10, fignum=1, namefig='dummy_contours.png', figfolder="",
                          savefig=False, **kwargs):
    """Creates a plot with the contours of two input datasets for comparison

    Input
    -----
    data1
    data2: 2d np.arrays
        Input arrays to compare
    plotwcs: WCS
        WCS used to set the plot if provided
    labels: tuple/list of 2 str
        Labels for the plot
    levels: list of floats
        Levels to be used for the contours. Calculated if None.
    fignum: int
        Number for the figure
    namefig: str
        Name of the figure to be saved (if savefig is True)
    figfolder: str
        Name of the folder for the figure
    savefig: bool
        If True, will save the figure as namefig

    Creates
    -------
    Plot with contours of the two input dataset
    """
    np.seterr(divide='ignore', invalid='ignore')

    # Getting the range of relevant fluxes
    lowlevel_d1, highlevel_d1 = get_flux_range(data1)

    fig, ax = open_new_wcs_figure(fignum, plotwcs)

    # Defining the levels for MUSE
    if levels is not None:
        levels_d1 = levels
    else:
        levels_d1 = np.linspace(np.log10(lowlevel_d1),
                                  np.log10(highlevel_d1),
                                  nlevels)
    # Plot contours for MUSE
    cdata1 = ax.contour(np.log10(data1), levels_d1, colors='k',
                          origin='lower', linestyles='solid')

    levels_d2 = cdata1.levels
    # Plot contours for Ref
    cdata2 = ax.contour(np.log10(data2), levels=levels_d2, colors='r',
                        origin='lower', alpha=0.5, linestyles='solid')

    ax.set_aspect('equal')
    h1, _ = cdata1.legend_elements()
    h2, _ = cdata2.legend_elements()
    ax.legend([h1[0], h2[0]], [labels[0], labels[1]])

    if "title" in kwargs:
        plt.title(kwargs.pop('title'))
    plt.tight_layout()
    if savefig:
        plt.savefig(joinpath(figfolder, namefig))
    np.seterr(divide='warn', invalid='warn')

def plot_compare_diff(data1, data2, plotwcs=None, figfolder="", percentage=5, fignum=1,
                      namefig="dummy_diff.ong", savefig=False, **kwargs):
    """

    Parameters
    ----------
    data1
    data2
    figfolder
    fignum
    namefig
    savefig
    kwargs

    Returns
    -------
    """
    fig, ax = open_new_wcs_figure(fignum, plotwcs)
    ratio = 100. * (data2 - data1) / (data1 + 1.e-12)
    im = ax.imshow(ratio, vmin=-percentage, vmax=percentage)
    cbar = fig.colorbar(im, shrink=0.8)

    if "title" in kwargs:
        plt.title(kwargs.pop('title'))
    plt.tight_layout()
    if savefig:
        plt.savefig(joinpath(figfolder, namefig))

def plot_compare_cuts(data1, data2, labels=('X', 'Y'), figfolder="", fignum=1,
                 namefig="dummy_polypar.png", ncuts=11, savefig=False, **kwargs):
    """

    Input
    -----
    data1
    data2
    label1
    label2
    figfolder
    fignum
    namefig
    savefig
    kwargs

    Creates
    -------
    Plot with a comparison of the two data arrays using regular X and Y cuts
    """

    fig, ax = open_new_wcs_figure(fignum)

    # Getting the range of relevant fluxes
    lowlevel_d1, highlevel_d1 = get_flux_range(data1)

    diffima = (data2 - data1) * 200. / (lowlevel_d1 + highlevel_d1)
    chunk_x = data1.shape[0] // (ncuts + 1)
    chunk_y = data1.shape[1] // (ncuts + 1)

    c1 = ax.plot(diffima[np.arange(ncuts) * chunk_x, :].T, 'k-', label=labels[0])
    c2 = ax.plot(diffima[:, np.arange(ncuts) * chunk_y], 'r-', label=labels[1])
    ax.legend(handles=[c1[0], c2[0]], loc=0)
    ax.set_ylim(-20, 20)
    ax.set_xlabel("[pixels]", fontsize=20)
    ax.set_ylabel("[%]", fontsize=20)

    if "title" in kwargs:
        plt.title(kwargs.pop('title'))
    plt.tight_layout()
    if savefig:
        plt.savefig(joinpath(figfolder, namefig))

def plot_polypar(polypar, labels=("Data 1","Data 2"), figfolder="", fignum=1,
                 namefig="dummy_polypar.png", savefig=False, **kwargs):
    """Creating a plot showing the normalisation arising from a polypar object

    Parameters
    ----------
    polypar
    label1
    label2
    foldfig
    namefig

    Returns
    -------

    """
    # Opening the figure
    fig, ax = open_new_wcs_figure(fignum)

    # Getting the x, y to plot
    (x, y) = (polypar.med[0][polypar.selection],
              polypar.med[1][polypar.selection])
    ax.plot(x, y, '.')
    ax.set_xlabel(labels[0])
    ax.set_ylabel(labels[1])
    ax.plot(x, my_linear_model(polypar.beta, x), 'k')

    if "title" in kwargs:
        plt.title(kwargs.pop('title'))
    plt.tight_layout()
    if savefig:
        plt.savefig(joinpath(figfolder, namefig))

#########################################################################
# Main class
#                           GraphMuse
#########################################################################
class GraphMuse(object):
    """Graphic output to check MUSE data reduction products
    """

    def __init__(self, pdf_name='drs_check.pdf',
            figsize=(10,14), rect_layout=[0, 0.03, 1, 0.95], verbose=True):
        """Initialise the class for plotting the outcome results
        """
        self.verbose = verbose
        self.pdf_name = pdf_name
        self.pp = PdfPages(pdf_name)
        self.figsize = figsize
        self.rect_layout = rect_layout
        self.npages = 0

    def close(self):
        self.pp.close()

    def savepage(self):
        self.pp.savefig()
        plt.close()
        self.npages += 1

    def start_page(self):
        """Start the page
        """
        if self.verbose :
            print_fig("Starting page {0}".format(self.npages+1))
        plt.figure(figsize=self.figsize)

    def plot_page(self, list_data):
        """Plot a set of blocks, each made of a set of spectra or
        images. This is for 1 page
        It first counts the number of lines needed according to the
        separation for images (default is 2 per line, each image taking 2 lines)
        and spectra (1 spectrum per line over 2 columns)
        """
        if len(list_data) == 0 :
            print_fig("WARNING: datalist is empty, no plots will be created")
            return

        self.start_page()
        nspectra_blocks, nimages_blocks = 0, 0
        nlines = 0
        if isinstance(list_data, MuseSetSpectra) | isinstance(list_data, MuseSetImages):
            plt.suptitle(list_data.subtitle)
            list_data = [list_data]

        for data in list_data :
            if isinstance(data, MuseSetSpectra):
                nspectra_blocks += 1
                nlines += data.__len__()
            elif isinstance(data, MuseSetImages):
                nimages_blocks += 1
                nlines += 2 * data.__len__()

        self.gs = gridspec.GridSpec(nlines, 2)
        self.list_ax = []
        self.count_lines = 0
        for data in list_data :
            if isinstance(data, MuseSetSpectra):
                self.plot_set_spectra(data)
            elif isinstance(data, MuseSetImages):
                self.plot_set_images(data)

        self.savepage()

    def plot_set_spectra(self, set_of_spectra=None):
        """Plotting a set of spectra
        Skipping the ones that are 'None'
        """

        # Set of sky lines to plot when relevant - add_sky_lines to True
        sky_lines = [5577., 6300., 6864., 7914., 8344., 8827.]

        if set_of_spectra is None:
            print_fig("ERROR: list of spectra is empty")
            return

        for spec in set_of_spectra:
            self.list_ax.append(plt.subplot(self.gs[self.count_lines,:]))
            self.count_lines += 1
            if spec is not None:
                spec.plot(title=spec.title, ax=self.list_ax[-1])
                if spec.add_sky_lines:
                    for line in sky_lines:
                        plt.axvline(x=line, color=spec.color_sky, linestyle=spec.linestyle_sky, alpha=spec.alpha_sky)

        plt.tight_layout(rect=self.rect_layout)

    def plot_set_images(self, set_of_images=None):
        """Plotting a set of images
        Skipping the ones that are 'None'
        """
        if set_of_images is None :
            print_fig("ERROR: list of images is empty")
            return

        for i in range(set_of_images.__len__()):
            image = set_of_images[i]
            count_cols = i%2
            if image is not None:
                self.list_ax.append(plt.subplot(self.gs[self.count_lines: self.count_lines + 2, count_cols]))
                image.plot(scale=image.scale, vmin=image.vmin, colorbar=image.colorbar, title=image.title, ax=self.list_ax[-1])
            self.count_lines += count_cols * 2

        plt.tight_layout(rect=self.rect_layout)


from datetime import datetime

from models.library_item import LibraryItem
from models.rent import Rent
from models.user import User
from services.handlers.rent_handlers.apply_discount_handler import ApplyDiscountHandler
from services.handlers.rent_handlers.calculate_fine_price_handler import (
    CalculateFinePriceHandler,
)
from services.handlers.rent_handlers.calculate_rent_price_handler import (
    CalculateRentPriceHandler,
)
from services.handlers.rent_handlers.inspect_item_handlers import InspectItemHandler
from services.handlers.rent_handlers.rent_request_payment_handler import (
    RentRequestPaymentHandler,
)
from services.handlers.rent_handlers.rent_return_payment_handler import (
    RentReturnPaymentHandler,
)
from services.handlers.rent_handlers.save_rent_handler import SaveRentHandler
from services.handlers.rent_handlers.update_book_catalogue_handler import (
    UpdateBookCatalogueHandler,
)
from services.payment.bank_account_payment_strategy import BankAccountPaymentStrategy
from services.payment.card_payment_strategy import CardPaymentStrategy
from services.payment.payment_strategy import PaymentStrategy
from services.singleton.singleton import singleton

@singleton
class LibraryManager:
    @classmethod
    def rent_library_item(
        cls,
        library_item: LibraryItem,
        user: User,
        expected_rent_end_date: datetime,
        payment_type: str,
    ):
        rent = cls.__create_rent(
            library_item=library_item,
            user=user,
            expected_rent_end_date=expected_rent_end_date,
        )

        payment_strategy = cls.__get_payment_strategy_from_type(payment_type)

        handler = cls.__get_rent_request_handlers()
        handler.handle(rent, payment_strategy)

        return rent

    @classmethod
    def return_library_item(
        cls,
        rent: Rent,
        payment_type: str,
    ):
        rent.rent_end_date = datetime.utcnow().date()
        payment_strategy = cls.__get_payment_strategy_from_type(payment_type)

        handler = cls.__get_rent_return_handlers()
        handler.handle(rent, payment_strategy)

        return rent

    @staticmethod
    def __create_rent(
        library_item: LibraryItem,
        user: User,
        expected_rent_end_date: datetime,
    ) -> Rent:
        rent = Rent(
            library_item=library_item,
            library_user=user,
            rent_start_date=datetime.utcnow(),
            expected_rent_end_date=expected_rent_end_date,
        )
        return rent

    @staticmethod
    def __get_rent_request_handlers():
        handler = CalculateRentPriceHandler()
        handler.set_next(ApplyDiscountHandler()).set_next(
            RentRequestPaymentHandler()
        ).set_next(UpdateBookCatalogueHandler()).set_next(SaveRentHandler())
        return handler

    @staticmethod
    def __get_rent_return_handlers():
        handler = InspectItemHandler()
        handler.set_next(CalculateFinePriceHandler()).set_next(
            RentReturnPaymentHandler()
        ).set_next(UpdateBookCatalogueHandler()).set_next(SaveRentHandler())
        return handler

    @staticmethod
    def __get_payment_strategy_from_type(payment_type: str) -> PaymentStrategy:
        if payment_type == "card":
            payment_strategy = CardPaymentStrategy()
        else:
            payment_strategy = BankAccountPaymentStrategy()
        return payment_strategy


import numpy as np
import matplotlib.pyplot as plt
import sys
import datetime
import time
import os
from scipy import optimize
import yaml
from matplotlib import rcParams
import matplotlib.patches as mpatches
from matplotlib import cm
from matplotlib.colors import ListedColormap, LinearSegmentedColormap
import matplotlib as mpl

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

def kappafunc(Lambda,alpha,r0):
	return alpha*np.exp(- r0/Lambda)*(1 + r0/Lambda)

def sigmafunc(Lambda,alpha,r0):
	return alpha*np.exp(- r0/Lambda)*(2 + 2*r0/Lambda + r0**2/Lambda**2)

def Deltakappa(LambdaLog,alpha,r0,gNewt,muc,r,hbar,omegam,Mprobe,n,g0):
	Lambda = 10**LambdaLog
	kappa = kappafunc(Lambda,alpha,r0)
	return 1/(np.sqrt(Mes)*gNewt)*(1/np.sqrt((muc**2*np.exp(4*r) + np.sinh(2*r)**2/2)))*np.sqrt(2*hbar*omegam**5/Mprobe)*(1/(8*np.pi*n*g0))*(1/kappa)-1

def Deltasigma(LambdaLog,alpha,r0,gNewt,muc,r,hbar,omegam,Mprobe,n,g0):
	Lambda = 10**LambdaLog
	sigma = sigmafunc(Lambda,alpha,r0)
	return 1/(np.sqrt(Mes)*gNewt)*(1/np.sqrt((muc**2*np.exp(4*r) + np.sinh(2*r)**2/2)))*np.sqrt(2*hbar*omegam**5/Mprobe)*(1/(4*np.pi*n*g0*epsilon))*(1/sigma)-1

def Deltakappares(LambdaLog,alpha,r0,gNewt,muc,r,hbar,omegam,Mprobe,n,g0):
	Lambda = 10**LambdaLog
	kappa = kappafunc(Lambda,alpha,r0)
	FN = gNewt*Mprobe
	return gNewt*Mprobe*kappa/FN

def Deltasigmares(Lambda,alpha,r0,gNewt,muc,r,hbar,omegam,Mprobe,n,g0):
	sigma = sigmafunc(Lambda,alpha,r0)
	FN = gNewt*Mprobe
	return gNewt*epsilon*Mprobe*sigma/FN

# Function to find all zeros, given a meshgrid:
def findAllZeros(func,X,Y,Z,r0,gNewt,muc,r,hbar,omegam,Mprobe,n,g0,bound,logX=True,logY=False):
	zeroList = []
	# If the x-values are in exponential form, convert to log
	if logX:
		Xuse = np.log10(X)
	else:
		Xuse = X
	if logY:
		Yuse = np.log10(Y)
	else:
		Yuse = Y
	for k in range(0,len(X)):
		rowList = []
		for l in range(0,len(X[0])-1):
			if Z[k,l]*Z[k,l+1] < 0 and np.isfinite(Z[k,l]) and np.isfinite(Z[k, l+1]):
				# Found a zero:
				xroot = optimize.brentq(func,Xuse[k,l],Xuse[k,l+1],args=(Yuse[k,l],r0,gNewt,muc,r,hbar,omegam,Mprobe,n,g0,bound))
				yroot = Yuse[k,l]
				rowList.append((xroot,yroot))
		zeroList.append(rowList)
	return zeroList

def extractZerosLine(zeroList,line=1):
	zerox = np.zeros(len(zeroList))
	zeroy = np.zeros(len(zeroList))
	for k in range(0,len(zerox)):
		if len(zeroList[k]) > line - 1:
			zerox[k] = zeroList[k][line-1][0]
			zeroy[k] = zeroList[k][line-1][1]
	haveZeros = np.where(zerox != 0)[0]
	return [zerox[haveZeros],zeroy[haveZeros]]

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

config = 'config.yaml'

# Load arguments from yaml file
args = {}
if type(config) == str:
	with open(config) as cfile:
		args.update(yaml.load(cfile))
elif type(config) == dict:
	args.update(config)
else:
	print("Failed to load config arguments")

hbar = float(args['hbar'])
G = float(args['G'])
c = float(args['c'])
e = float(args['e'])
muc = float(args['muc'])
g0 = float(args['g0'])
omegam = float(args['omegam'])
r0 = float(args['r0'])
epsilon = float(args['epsilon'])
r = float(args['r'])
n = float(args['n'])
Ms = float(args['Ms'])
Mes = float(args['Mes'])

Ms = float(args['Ms'])
rhos = float(args['rhos'])
rhop = float(args['rhop'])
Mprobe = float(args['Mprobe'])
rhobg = float(args['rhobg'])
Lambdamin = float(args['Lambdamin'])
Lambdamax = float(args['Lambdamax'])
alphamin = float(args['alphamin'])
alphamax = float(args['alphamax'])
lmin = float(args['lmin'])
lmax = float(args['lmax'])

nSample = int(args['nSample'])

gNewt = G*Ms/r0**2

alpharange = 10**(np.linspace(alphamin,alphamax,nSample))
lambdarange = 10**(np.linspace(lmin,lmax,nSample))

LambdaGrid, alphaGrid = np.meshgrid(lambdarange,alpharange)

# Plot the functions
rcParams.update({'figure.autolayout': True})
plt.rcParams['xtick.minor.size'] = 0
plt.rcParams['xtick.minor.width'] = 0
fig, ax = plt.subplots(figsize = (7, 6))
plt.xlabel('$\\lambda \, (\\mathrm{m})$', fontfamily = 'serif', fontsize = 15)
plt.ylabel('$|\\alpha|$', fontfamily = 'serif', fontsize = 15)
plt.xticks(fontsize=14)
plt.yticks(fontsize=14)
ax.set_ylim(1e-8,1e8)
ax.set_xlim(1e-5,1)

# Start loop that prints each bound in bounds

DeltakappaGrid = np.log10(Deltakappares(LambdaGrid,alphaGrid,r0,gNewt,muc,r,hbar,omegam,Mprobe,n,g0))
DeltasigmaGrid = np.log10(Deltasigmares(LambdaGrid,alphaGrid,r0,gNewt,muc,r,hbar,omegam,Mprobe,n,g0))

#plt.loglog(10**zerox1sigmares, zeroy1sigmares, alpha = 1, color = 'black', label = str(bound))

viridis = cm.get_cmap('viridis', 8)
#loglevels = [1e-20,1e-18,1e-16,1e-14,1e-12,1e-10,1e-1]
#levels = [-20, -18, -16, -14, -12, -10, -8, -6]
levels = [-8, -6, -4, -2, 0, 2, 4, 6, 8]
CS = ax.contourf(LambdaGrid, alphaGrid, DeltasigmaGrid, levels = levels, colors = viridis.colors)
plt.xscale('log')
plt.yscale('log')
clb = fig.colorbar(CS, extend = 'both')
clb.ax.tick_params(labelsize=12)
clb.set_label('$\\log_{10}(\\Delta F)$', labelpad=-40, y=1.05, rotation=0, fontsize = 12)
#ax.legend(loc = 'lower left', labelspacing = 0.4, fontsize = 12)
#ax.clabel(CS, inline=True, fontsize=10)
plt.savefig('alphalambdaforceplot.pdf')
plt.show()


import pygame
from random import randint

class Enemy(pygame.sprite.Sprite):
    def __init__(self, x, y, level):
        super().__init__()
        self.image_list = []
        self.level = level
        self.frame = 0

        for index in range(10):
            image_name = 'Pic\\Enemy' + str(level) + '\\Enemy' + str(level) + '_' + str(index+1) + '.png'
            self.image_list.append(pygame.image.load(image_name).convert_alpha())

        self.image_order = 0
        self.image = self.image_list[self.image_order]
        # self.image = pygame.image.load('Pic\Enemy1\Enemy1.png').convert_alpha()
        self.rect = self.image.get_rect(topleft=(x, y))

        self.speed = 1
        '''speed for each level'''
        # if self.level%4 >= 0.5:
        #     self.speed = 1*ceil(self.level/4)
        # elif self.level%4 < 0.5:
        #     self.speed = 1*floor(self.level/4)

        # print(f'level: {level}')
        # print(self.speed)

        self.lasers = pygame.sprite.Group()
        '''Make it collide perfectly'''
        self.mask = pygame.mask.from_surface(self.image)

        '''special enemy'''
        special_number = randint(0, 10)
        if special_number == 4:
            self.special = 'heart'
        elif special_number == 1:
            self.special = 'item'
        else:
            self.special = 'none'

        self.check_game_over = True

    def move(self):
        '''Movement speed of Enemy1'''
        if self.rect.x > 0:
            self.rect.x -= self.speed
        elif self.rect.x == 0:
            '''Constraint for enemies pos'''
            self.check_game_over = False
            # pygame.quit()
            # sys.exit()

    def pic(self):

        self.frame += 1
        if self.frame == 12:
            self.frame = 0
            self.image_order += 1

            if self.image_order >= len(self.image_list):
                self.image_order = 0

        self.image = self.image_list[self.image_order]

    def update(self):
        self.move()
        self.pic()
        if self.check_game_over is False:
            return False