import hngd.run
import hngd.default
import experimental_data
import numpy as np
import matplotlib.pyplot as plt

# TODO > En la tesis de Florian Passelaigue (2020 - Hydride
# nucleation-growth-dissolution model: Implementation in BISON) muestra
# barras de error para estos experimentos (no encontre de donde salen?).

"""
Generate plots for the experiments made by Kammenzind, published in Merlino
J. T., 'Experiments in hydrogen distribution in thermal gradients calculated
using BISON', M. Eng. Thesis, The Pennsylvania State University (2019).

This script runs experiments from the Experiment 1 Data Set. Experimental data
can be found in Appendix A, Tables A1-A14. In these experiments, specimens
containing various amounts of hydrogen were annealed while subjected to various
temperature gradients. The anneals were conducted for periods of time ranging
from weeks to months in order to approach equilibrium. The specimens were then
removed from heat, sectioned, and analyzed for total hydrogen content.

Zirconium alloys used include alpha-annealed Zircaloy-4, Zircaloy-1%Niobium and
Zircaloy-2.5%Niobium.

This script takes ~ 35 minutes to run all 28 experiments.

"""

slab_length = 2.54*1e-2
experiment_data = (slab_length, 0, 0, 1, 0)

model_parameters = hngd.default.model_parameters

# TSSp and TSSd of Zry-4 by Zanellato et al. (most experiments are with Zry-4).

model_parameters['TSSd0'] = 510800
model_parameters['Q_TSSd'] = 45610
model_parameters['TSSp0'] = 66440
model_parameters['Q_TSSp'] = 29630

# Diffusion coefficient for Zry-4 by Kammenzind et al.

#model_parameters['D0'] = 0.8e-7
#model_parameters['Ed'] = 0.34

# Diffusion coefficient for Zry-4 by Kearns.

model_parameters['D0'] = 7.73e-7
model_parameters['Ed'] = 0.47

#%% Simulate

for i, (experiment, data) in enumerate(experimental_data.linear_cases.items()):

    print(f'\n- Running experiment {experiment}. Simulation {i+1} out of {len(experimental_data.linear_cases)}.')

    simulation_data = (experiment, 70, 2, 500, 0.05, 'mHNGD')

    temperature_data = np.array([[                np.nan,                       0,              slab_length],
                                 [                     0, data['low_temperature'], data['high_temperature']],
                                 [data['annealing_time'], data['low_temperature'], data['high_temperature']]])

    initial_hydrogen_data = np.array([[                       0,             slab_length],
                                      [data['initial_hydrogen'], data['initial_hydrogen']]])

    model_parameters['Q_star'] = data['heat_of_transport']

    hngd.run.simulation(temperature_data, initial_hydrogen_data, experiment_data, simulation_data, model_parameters,
                        save_results=False, save_last_concentration_profile=True)

#%% Plot

for experiment, data in experimental_data.linear_cases.items():

    # Load experimental and simulated data.

    pos_exp = data['midpoint_location']
    hyd_exp = data['hydrogen_concentration']

    pos_sim, temp_sim, Css_sim, Cp_sim = np.loadtxt(f'Outputs/{experiment}_last_concentration_profile.txt',
                                                    skiprows=1, unpack=True)
    hyd_sim = Css_sim + Cp_sim

    # Plot.

    fig, ax1 = plt.subplots(figsize=(7,4))

    fig.canvas.manager.set_window_title(f'Simulation of the Kammenzind linear case {experiment}')

    ax1.scatter(pos_exp*1e2, hyd_exp, label='Experimental')
    ax1.plot(pos_sim*1e2, hyd_sim, label='Simulated')

    ax1.axhline(y=data['initial_hydrogen'], linestyle='dotted', color='k')

    ax1.annotate(f'$C_0$ = {np.round(data["initial_hydrogen"], 1)} wt.ppm',
                xy=(1.3,data["initial_hydrogen"]), xytext=(0,3), textcoords='offset points', va='bottom')

    ax1.set_xlabel('Distance [cm]')
    ax1.set_ylabel('Hydrogen content [wt.ppm]', color='#1f77b4')

    ax1.set_xlim([0, slab_length*1e2])
    ax1.set_ylim(bottom=0)

    ax1.tick_params(axis='y', labelcolor='#1f77b4')

    ax1.legend(loc='upper center')

    ax2 = ax1.twinx()

    ax2.plot(pos_sim*1e2, temp_sim, color='#ff7f0e', linestyle='dashed')

    ax2.set_ylabel('Temperature [K]', color='#ff7f0e')

    ax2.tick_params(axis='y', labelcolor='#ff7f0e')

    fig.tight_layout()

    fig.savefig(f'Outputs/linear_{experiment}.png', bbox_inches='tight')

plt.show()


from modules.ObjectDetection.opencvdnn import do_object_detection as detect
import os

def obj_dection(path, network="MobileNet", dir=""):
    import requests
    if network == "MobileNet":
        prototxt = dir + "MobileNetSSD_deploy.prototxt.txt"
        model = dir + "MobileNetSSD_deploy.caffemodel"
    else:
        raise Exception("Network not provided")

    if not os.path.exists(prototxt):
        file_url = "http://media.liontao.xin/MobileNetSSD_deploy.prototxt.txt?attname=&e=1545901370&token=8D-fPY7fZfvNQ_YlcCHphmf-beQ7s5-ahx1C_WJ4:eJEMiBlqucJesL3efchu7cHW7gU"
        file_path = prototxt

        from contextlib import closing
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"}
        with closing(requests.get(file_url, headers=headers, stream=True)) as response:
            chunk_size = 100
            content_size = int(response.headers['content-length'])
            data_count = 0
            with open(file_path, "wb") as file:
                for data in response.iter_content(chunk_size=chunk_size):
                    file.write(data)
                    data_count = data_count + len(data)
                    now_jd = (data_count / content_size) * 100
                    print("\r Progress: {:.2f}% ({:d}/{:d}) - {}".format(now_jd, data_count, content_size, file_path),
                          end="")
            print("\r\n[INFO]Download Completed.")

    if not os.path.exists(model):
        file_url = "http://media.liontao.xin/MobileNetSSD_deploy.caffemodel?attname=&e=1545901361&token=8D-fPY7fZfvNQ_YlcCHphmf-beQ7s5-ahx1C_WJ4:8DDL7DJyP0qnQt4b-tHBx9OsHS4"
        file_path = model

        from contextlib import closing
        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"}
        with closing(requests.get(file_url, headers=headers, stream=True)) as response:
            chunk_size = 1024
            content_size = int(response.headers['content-length'])
            data_count = 0
            with open(file_path, "wb") as file:
                for data in response.iter_content(chunk_size=chunk_size):
                    file.write(data)
                    data_count = data_count + len(data)
                    now_jd = (data_count / content_size) * 100
                    print("\r Progress: {:.2f}% ({:d}/{:d}) - {}".format(now_jd, data_count, content_size, file_path),
                          end="")
            print("\r\n[INFO]Download Completed.")

    if os.path.exists(path) and os.path.isfile(path) and os.path.isfile(prototxt) and os.path.isfile(model):
        image, category = detect(path, prototxt=prototxt, model=model)
        return image, category
    else:
        raise FileNotFoundError

if __name__ == '__main__':
    _, r = obj_dection(path="image.jpg")
    print(r)


from turtle import circle
from rapidfuzz import process
from dataclasses import dataclass

@dataclass
class Airport:
    name: str
    code: str
    city: str
    country: str

airports = [
    Airport("Suvarnabhumi Airport", "BKK", "Bangkok", "Thailand"),
    Airport("Shogun Airport", "SHO", "Shogunus", "Shogunium"),
    Airport("Arthur Airport", "ATA", "Chiba", "Japan"),
    Airport("Shonen Airport", "SHA", "Sapporo", "Japan")
]
airport_attr = {
    attr: {getattr(airport, attr): airport for airport in airports}
    for attr in ('name', 'location_code', 'city', 'country')
}
#print(*airport_attr, sep='\n')
query = input("Enter your search : ")

matches = {
    attr: process.extract(query, value.keys()) for attr, value in airport_attr.items()
}

for paramiter, value in matches.items():
    print(paramiter, {item: airport_attr[paramiter][item] for item, score, _ in value if score > 60}, sep='\n', end='\n\n')


from ray.rllib.algorithms import ppo
from ray.rllib.env.env_context import EnvContext
import argparse
import os
#import yaml
import ruamel.yaml as yaml
import sys

print("Training automatically with Ray Tune")
#results = tune.run(args.run, config=config, stop=stop)

#tuner = tune.Tuner(
#    args.run, param_space=config, run_config=air.RunConfig(stop=stop)
#)
#results = tuner.fit()

#ray.shutdown()

import argparse
import os

from ray.rllib.utils.test_utils import check_learning_achieved
from helper_config import convert_yaml_into_readable_format, convert_runable_into_2_0_format, register_custom_env, \
    register_algorithm_from_config, register_custom_action_distribution, register_custom_model, update_GPU_resources, \
    set_experiment_name, check_for_non_config_callbacks, check_for_custom_callbacks, check_for_custom_eval_function, \
    check_for_constraint_amount_lambda_model

parser = argparse.ArgumentParser()
parser.add_argument(
    "--run", type=str, default="PPO", help="The RLlib-registered algorithm to use."
)
parser.add_argument("--num-cpus", type=int, default=0)
parser.add_argument(
    "--framework",
    choices=["tf", "tf2", "tfe", "torch"],
    default="torch",
    help="The DL framework specifier.",
)
parser.add_argument("--eager-tracing", action="store_true")
parser.add_argument("--use-prev-action", action="store_true")
parser.add_argument("--use-prev-reward", action="store_true")
parser.add_argument(
    "--as-test",
    action="store_true",
    help="Whether this script should be run as a test: --stop-reward must "
    "be achieved within --stop-timesteps AND --stop-iters.",
)
parser.add_argument(
    "--stop-iters", type=int, default=200, help="Number of iterations to train."
)
parser.add_argument(
    "--stop-timesteps", type=int, default=100000, help="Number of timesteps to train."
)
parser.add_argument(
    "--stop-reward", type=float, default=150.0, help="Reward at which we stop training."
)

if __name__ == "__main__":
    import ray
    from ray import air, tune

    #args = parser.parse_args()

    ray.init()#num_cpus=args.num_cpus or None)
    """
    configs = {
        "PPO": {
            "num_sgd_iter": 5,
            "model": {
                "vf_share_layers": True,
            },
            "vf_loss_coeff": 0.0001,
        },
        "IMPALA": {
            "num_workers": 2,
            "num_gpus": 0,
            "vf_loss_coeff": 0.01,
        },
    }

    config = dict(
        configs[args.run],
        **{
            "env": StatelessCartPole,
            # Use GPUs iff `RLLIB_NUM_GPUS` env var set to > 0.
            "num_gpus": int(os.environ.get("RLLIB_NUM_GPUS", "0")),
            "model": {
                "use_lstm": True,
                "lstm_cell_size": 256,
                "lstm_use_prev_action": args.use_prev_action,
                "lstm_use_prev_reward": args.use_prev_reward,
            },
            "framework": args.framework,
            # Run with tracing enabled for tfe/tf2?
            "eager_tracing": args.eager_tracing,
        }
    )

    stop = {
        "training_iteration": args.stop_iters,
        "timesteps_total": args.stop_timesteps,
        "episode_reward_mean": args.stop_reward,
    }

    # To run the Algorithm without ``Tuner.fit``, using our LSTM model and
    # manual state-in handling, do the following:

    # Example (use `config` from the above code):
    # >> import numpy as np
    # >> from ray.rllib.algorithms.ppo import PPO
    # >>
    # >> algo = PPO(config)
    # >> lstm_cell_size = config["model"]["lstm_cell_size"]
    # >> env = StatelessCartPole()
    # >> obs = env.reset()
    # >>
    # >> # range(2) b/c h- and c-states of the LSTM.
    # >> init_state = state = [
    # ..     np.zeros([lstm_cell_size], np.float32) for _ in range(2)
    # .. ]
    # >> prev_a = 0
    # >> prev_r = 0.0
    # >>
    # >> while True:
    # >>     a, state_out, _ = algo.compute_single_action(
    # ..         obs, state, prev_a, prev_r)
    # >>     obs, reward, done, _ = env.step(a)
    # >>     if done:
    # >>         obs = env.reset()
    # >>         state = init_state
    # >>         prev_a = 0
    # >>         prev_r = 0.0
    # >>     else:
    # >>         state = state_out
    # >>         prev_a = a
    # >>         prev_r = reward
    """ or None
    #print(config)

    if len(sys.argv) > 1:
        yaml_file_name = sys.argv[1]
    elif os.environ.get("YAML_FILE_NAME", None) is not None:
        yaml_file_name = os.environ.get("YAML_FILE_NAME", None)
    else:
        # yaml_file_name = "finance-ppo.yaml" # "custom-gridworld-riskppo.yaml"#"cartpole-ppo-test.yaml"  # "cartpole-ppo-test.yaml"
        # yaml_file_name = "finance-ppo-12.yaml"
        # yaml_file_name = "finance-ppo-2-working-12-12-21.yaml"
        # yaml_file_name = "finance-ppo-2-one-state.yaml"
        # yaml_file_name = "finance-ppo-penalty-state.yaml"
        #yaml_file_name = "finance-ppo-38.yaml"#"finance-ppo-36.yaml"#"finance-ppo-34.yaml"
        #yaml_file_name = "finance-ppo-36.yaml"
        #yaml_file_name = "cartpole-ddpg.yaml"

        #yaml_file_name = "finance-ddpg-4.yaml"
        #yaml_file_name = "finance-ppo-43.yaml"
        #yaml_file_name = "finance-ppo-47.yaml"
        #yaml_file_name = "finance-ppo-2-interval.yaml"
        #yaml_file_name = "pendulum-td3.yaml"
        #yaml_file_name = "pendulum-td3-custom.yaml"
        #yaml_file_name = "finance-td3-1.yaml"
        #yaml_file_name = "finance-ppo-57.yaml"
        #yaml_file_name = "finance-ppo-classic-1.yaml"
        #yaml_file_name = "finance-ddpg-1-interval.yaml"
        #yaml_file_name = "short-ppo-38.yaml"#"short-ppo-30.yaml"#"short-ppo-15.yaml"#"short-ppo-2.yaml"#"short-ppo-2.yaml"
        #yaml_file_name = "cartpole-stateless-lstm-2.yaml"
        #yaml_file_name = "short-ppo-155.yaml"#"short-ppo-141.yaml"#"short-ppo-101.yaml"#"short-ppo-90.yaml"#"short-ppo-85.yaml"#"short-ppo-85.yaml" #"short-ppo-69.yaml"#"short-ppo-53.yaml"#"short-ppo-51.yaml"#"short-ppo-49.yaml"#"short-ppo-44.yaml" #41 is working with custom_dirichlet distribution
        #yaml_file_name = "cartpole-stateless-lstm-1.yaml"
        #yaml_file_name = "ppo-autoreg-test-4.yaml"
        #yaml_file_name = "ppo-autoreg-test-6.yaml"
        #yaml_file_name = "ppo-autoreg-test-9.yaml"
        #yaml_file_name = "ppo-autoreg-test-12.yaml"
        #yaml_file_name = "ppo-autoreg-test-13.yaml"
        #yaml_file_name = "ppo-autoreg-const-20.yaml"
        #yaml_file_name = "ppo-autoreg-const-37.yaml"
        #yaml_file_name = "ppo-autoreg-const-40.yaml"
        #yaml_file_name = "ppo-autoreg-const-54.yaml"
        yaml_file_name = "ppo-autoreg-const-372.yaml"#"ppo-autoreg-const-354.yaml"#"ppo-autoreg-const-344.yaml"#"ppo-autoreg-const-155.yaml"

    print("RAY INIT")

    #yaml_file_name = "cartpole-stateless-framestacking.yaml"
    #yaml_file_name = "cartpole-stateless-lstm.yaml"
    #yaml_file_name = "cartpole-stateless-attention.yaml"

    with open(f"run_config/{yaml_file_name}", "r") as stream:
        try:
            run_config_raw = next(iter(yaml.safe_load(stream).values()))
        except yaml.YAMLError as exc:
            print(exc)

    run_name = yaml_file_name.replace(".yaml", "")

    PROJECT_NAME = "const_autoreg_2"
    print(run_config_raw)

    run_config_readable = convert_yaml_into_readable_format(run_config_input=run_config_raw)
    run_config_readable = register_custom_env(run_config_readable)
    run_config_readable = register_custom_action_distribution(run_config_readable)
    run_config_readable = register_algorithm_from_config(run_config_readable)
    run_config_readable = register_custom_model(run_config_readable)
    run_config_readable = check_for_constraint_amount_lambda_model(run_config_readable)
    run_config_readable = update_GPU_resources(run_config_readable)
    run_config_readable = check_for_custom_eval_function(run_config_readable)
    run_config_readable = check_for_custom_callbacks(run_config_readable)
    run_config_readable = check_for_non_config_callbacks(run_config_readable, group_name=run_name, project_name=PROJECT_NAME)
    run_config_readable = set_experiment_name(run_config_readable, run_name=run_name)

    print(run_config_readable)
    #must be last
    trainable, dict_param_space, dict_run_config = convert_runable_into_2_0_format(run_config_readable)

    #print(dict_run_config)

    #tuner = tune.Tuner(
    #    trainable=args.run, param_space=config, run_config=air.RunConfig(stop=stop, verbose=2)
    #)

    tuner = tune.Tuner(
        trainable=trainable, param_space=dict_param_space, run_config=air.RunConfig(**dict_run_config)
    )

    results = tuner.fit()

    ray.shutdown()


from datetime import datetime, date, timedelta

di = date(2021,3,1)
df = date(2021,11,8)

T = df-di
print('total time:', T)    # 252 d = 8 m
print('event to event time:', T/4 - timedelta(days=7))  #  d = 2 m

T4 = T/4
for i in range(4):
    d = di+i*T4
    print(f"e{i}: {d}")


import os
from django.utils.timezone import now
from datetime import datetime

from django.db import models
from django.contrib.auth.models import User
from phone_field import PhoneField

# Create your models here.

class Tags(models.Model):
    tg_name = models.CharField('тэг', max_length=200, null=True, unique=True)

    def __str__(self):
        return self.tg_name

    class Meta:
        verbose_name = 'Тег'
        verbose_name_plural = 'Теги'

class Calendar(models.Model):
    cal_date = models.DateField('Дата')
    cal_text = models.TextField('Текст')
    cal_tag = models.ManyToManyField(Tags, blank=True, verbose_name='Тэг')

    def __str__(self):
        return self.cal_text

    class Meta:
        verbose_name = 'Календарь'
        verbose_name_plural = 'Календарь'

class Problems(models.Model):
    STAT_dif = (('1', 'простая'), ('2', 'обычная'), ('3', 'сложная'), ('4', 'ОЧЕНЬ СЛОЖНАЯ'))
    STAT = (('актуально', 'актуально'), ('решено', 'решено'))
    pr_name = models.CharField('Наименование проблемы', max_length=100)
    pr_status = models.CharField('Статус', choices=STAT, max_length=50)
    pr_dif = models.CharField('Сложность', choices=STAT_dif, max_length=50)
    pr_solution = models.TextField('Решение')
    pr_document = models.FileField('Файл', blank=True)
    pr_calendar = models.ManyToManyField(Calendar, blank=True, verbose_name='События')

    def __str__(self):
        return self.pr_name

    class Meta:
        verbose_name = 'Проблема'
        verbose_name_plural = 'Проблемы'

class Tasks(models.Model):
    STAT_dif = (('1', 'простая'), ('2', 'обычная'), ('3', 'сложная'), ('4', 'ОЧЕНЬ СЛОЖНАЯ'))
    STAT = (('актуально', 'актуально'), ('выполнено', 'выполнено'))
    tk_name = models.CharField('Наименование задачи', max_length=50)
    tk_status = models.CharField('Статус', choices=STAT, max_length=50)
    tk_dif = models.CharField('Сложность', choices=STAT_dif, max_length=50)
    tk_type = models.ManyToManyField(Tags, blank=True, verbose_name='Тэг')
    tk_problem = models.ManyToManyField(Problems, blank=True, verbose_name='Проблемы')
    tk_calendar = models.ManyToManyField(Calendar,  blank=True, verbose_name='События')

    def __str__(self):
        return self.tk_name

    class Meta:
        verbose_name = 'Задача'
        verbose_name_plural = 'Задачи'

class Projects(models.Model):
    STAT = (('открыт', 'открыт'), ('завершен', 'завершен'))
    pr_name = models.CharField('Название проекта', max_length=50)
    pr_team = models.ManyToManyField(User)
    pr_start = models.DateField('Начало работ')
    pr_deadline = models.DateField('Завершение работ')
    pr_status = models.CharField('Статус', choices=STAT, max_length=50)
    pr_calendar = models.ManyToManyField(Calendar, blank=True, verbose_name='События')
    pr_task = models.ManyToManyField(Tasks, blank=True, verbose_name='Задачи')

    def __str__(self):
        return self.pr_name

    class Meta:
        verbose_name = 'Проект'
        verbose_name_plural = 'Проекты'

class Messages(models.Model):
    mes_from = models.ForeignKey(User, related_name='author', on_delete=models.SET_NULL, null=True, verbose_name='От')
    mes_to = models.ManyToManyField(User, related_name='to',  verbose_name='Кому')
    mes_text = models.TextField('Текст сообщения')
    mes_tag = models.ManyToManyField(Tags)

    class Meta:
        verbose_name = 'Сообщение'
        verbose_name_plural = 'Сообщения'

class Jobs(models.Model):
    job_name = models.CharField('должность', max_length=200, null=True, unique=True)

    def __str__(self):
        return self.job_name

    class Meta:
        verbose_name = 'Должность'
        verbose_name_plural = 'Должности'

class Information(models.Model):
    info_employee = models.OneToOneField(User, on_delete=models.CASCADE, verbose_name='Сотрудник')
    info_job = models.ManyToManyField(Jobs, blank=True, verbose_name='Должность')
    info_tel = PhoneField('Номер телефона', blank=True, help_text='Телефон | ext. ')
    info_image = models.ImageField('Фото', default="unnamed.png", null=True, blank=True)

    def __str__(self):
        return self.info_employee.get_username()

    def filename(self):
        return os.path.basename(self.info_image.name)

    class Meta:
        verbose_name = 'Информация о работнике'
        verbose_name_plural = 'Информация о работниках'

class Documents(models.Model):
    STAT = (('принят', 'принят'), ('на рассмотрении', 'на рассмотрении'), ('отклонен', 'отклонен'))
    doc_name = models.CharField('Название', max_length=50)
    doc_owner = models.ManyToManyField(User, 'Владельцы')
    doc_date = models.DateField('Последние изменения', default=datetime.now)
    doc_tag = models.ManyToManyField(Tags, 'Тэг')
    doc_doc = models.FileField('Файл', blank=True)
    doc_link = models.URLField('Ссылка на документ', blank=True, max_length=100)
    doc_calendar = models.ManyToManyField(Calendar, blank=True, verbose_name='События')
    doc_task = models.ForeignKey(Tasks, verbose_name='Задача', blank=True, null=True, on_delete=models.SET_NULL)
    doc_project = models.ManyToManyField(Projects, verbose_name='Для проекта')
    doc_acc = models.CharField('Статус', choices=STAT, null=True, max_length=50, default='на рассмотрении')

    def __str__(self):
        return self.doc_name

    def filename(self):
        return os.path.basename(self.doc_doc.name)

    class Meta:
        verbose_name = 'Документы'
        verbose_name_plural = 'Документы'

class Comments(models.Model):
    com_title = models.CharField('Заголовок комментария', max_length=50)
    com_user = models.ForeignKey(User, verbose_name='Пользователь', on_delete=models.SET_NULL, null=True)
    com_text = models.TextField('Текст комментария')
    com_date = models.DateTimeField(default=now, editable=False)
    com_teg = models.ManyToManyField(Tags, blank=True, verbose_name='Тэг')
    com_doc = models.ManyToManyField(Documents, blank=True, verbose_name='Документы')
    com_proj = models.ForeignKey(Projects, blank=True, null=True, on_delete=models.CASCADE, verbose_name='Проекты')
    com_tasks = models.ManyToManyField(Tasks, blank=True, verbose_name='Задачи')
    com_prob = models.ManyToManyField(Problems, blank=True, verbose_name='Проблемы')

    def __str__(self):
        return self.com_title

    class Meta:
        verbose_name = 'Комментарий'
        verbose_name_plural = 'Комментарии'


from sqlalchemy import engine_from_config
from settings import get_config_dict
from mapping import DBSession, PlanetOsmLine, PlanetOsmPolygon
from geojson import Feature, FeatureCollection, dump, dumps
from sqlalchemy.sql import func
import json

settings = get_config_dict()

engine = engine_from_config(settings, 'sqlalchemy.', echo=True)
planet_engine = engine_from_config(settings, 'osm.', echo=False)
DBSession.configure(binds={
    PlanetOsmLine:planet_engine,
    PlanetOsmPolygon:planet_engine
    })
ses = DBSession

def group(inputfile, outputfile):
    """This reads exported file from dataset.freeze

    Data consists of all the streets in Maribor grouped by streets and years
    Data looks like {"results": [ {"leto_odtujitve":string, "cnt":number,
    "tekst_odseka_ulice": ""}]}

    Output is JSON file with streets in first layer and years with counts in
    second: { "street name":{"year": number of occurences}}
    """

    d = defaultdict(lambda: defaultdict(int))
    maxSteals = 0
    with open(inputfile, "r") as f:
        json_data = json.load(f)
        for result in json_data["results"]:
            ulica = result["tekst_odseka_ulice"]
            leto = result["leto_odtujitve"]
            stevilo_kraj = result["cnt"]
            d[ulica][leto]=stevilo_kraj
            if stevilo_kraj > maxSteals:
                maxSteals = stevilo_kraj
        d["max_steals"] = maxSteals
    json.dump(d, open(outputfile, "w"))

def get_street_geometries(cache_file):
    """Gets distinct list of all street names from DB

    And for each of street those streets search for same named street in OSM DB

    If it is found geometry geojson part is saved in file based dict keyed as
    street name
    """
    found,missing = (0,0)
    with shelve.open(cache_file) as streets_geo_db:
        db = dataset.connect('sqlite:///kraje.db')
        streets = db.query('SELECT distinct(tekst_odseka_ulice) FROM kraje WHERE ' +
            'tekst_ceste_naselja == "MARIBOR"')
        for street in streets:
            street_name = street["tekst_odseka_ulice"]
            #Skips already inserted streets
            if street_name in streets_geo_db:
                continue
            geo_streets = PlanetOsmLine.get_street(street_name)
            geo = {
                    "type": "GeometryCollection",
                    "geometries": []
                    }
            name = None
            #Geometry collection of all the parts of street with same name in
            #OSM
            for geo_street in geo_streets:
                name = geo_street.name
                geo["geometries"].append(json.loads(geo_street.geodata));
            if (found+missing)%100 == 0:
                print ("O")
            elif (found+missing)%20 == 0:
                print (".")
            #Skips streets which weren't found in geo_streets
            if name is not None:
                streets_geo_db[street_name] = geo
                found +=1
            else:
                missing += 1
        print ("Found {}/{} {.2f}% streets".format(found, found+missing,
            found/(found+missing)*100))

if __name__ == "__main__":
    #from collections import defaultdict
    #group("./maribor_group.json", "./kraje_tmp.json")
    #import dataset
    import shelve
    cache_file = "./streets_maribor_geo"
    #get_street_geometries(cache_file)
    min_year = 2008
    max_year = 2014
    range_years = range(min_year, max_year+1)
    with shelve.open(cache_file) as streets_geo_db, \
            open("./kraje_tmp.json", "r") as city_grouped:
        data = json.load(city_grouped);
        max_steals = data["max_steals"]
        del data["max_steals"]
        features = []
        for street_name, years in data.items():
            geo = None
            if street_name in streets_geo_db:
                geo = streets_geo_db[street_name]
            else:
                continue
            prop = {'name': street_name}
            for year in range_years:
                if str(year) in years:
                    value = years[str(year)]/max_steals*8
                    value_normal = years[str(year)]
                else:
                    value = 0
                    value_normal = 0
                prop["{}_class".format(year)] = value
                prop[year] = value_normal
            print(prop)
            fet = Feature(geometry=geo, properties=prop)
            features.append(fet)
        vse = FeatureCollection(features)
        dump(vse, open("maribor_class.geojson", "w"))


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

def plot_means(sim) :

    areas = sim.SELECTED_META_AREAS
    meansdf = sim.meandf
    des_means = sim.targets.iloc[:,2:]
    des_means = des_means.as_matrix()

    fig = plt.figure(figsize=(16, 10))

    if np.any(meansdf.TIC=='NOTIC') :
        for i,area in zip(xrange(len(areas)), areas):

            select = (meansdf.META_AREA==area) & (meansdf.TIC=='NOTIC')
            ax = fig.add_subplot(5,2,(i*2 +1))
            y = meansdf[select].iloc[:,5:-1].as_matrix().T
            ax.plot(y, lw=2)
            x = np.linspace(0,sim.INNER_WINDOW-1, sim.MEASURE_INTERVALS )
            ax.plot(x, des_means[i*2,:], c="red")

    if np.any(meansdf.TIC=='TIC') :
        for i,area in zip(xrange(len(areas)), areas):

            select = (meansdf.META_AREA==area) & (meansdf.TIC=='TIC')
            ax = fig.add_subplot(5,2,(i*2+2))
            y = meansdf[select].iloc[:,5:-1].as_matrix().T
            ax.plot(y, lw=2)
            x = np.linspace(0,sim.INNER_WINDOW-1, sim.MEASURE_INTERVALS )
            ax.plot(x, des_means[((i*2)+1),:], c="red")

# we define a general plot function for a layer
def plot_layer_gs(data,row,xaxis=True, label="layer",N=3) :

    gs = gridspec.GridSpec(rows, 20 )

    # paramenters
    colors = ['r','g','b']    # color types
    xlims =[250,stime+50]    # limits on the x axis
    ylims = [-0.1,4.1]    # limits on the y axis
    linewidth = 2    # width of the plot line
    plotalpha = 0.5    # alpha color of the line
    fillalpha = 0.01    # alpha color of the filled area

    plt.subplot(gs[row,:2])    # plot within the subplot window
    plt.axis("off")
    plt.text(.1,.2,label,fontsize=11)

    plt.subplot(gs[row,2:])    # plot within the subplot window

    # for each channel
    x = arange(stime)
    cols=iter(cm.rainbow(np.linspace(0,1,N)))
    for i in xrange(N) :
        color = next(cols)
        y = data[i,:]
        # plot the line
        plt.plot(y, color=color, linewidth=linewidth, alpha=plotalpha)
        # fill the area below the line
        plt.fill_between(x, y, 0, facecolor=color, alpha=fillalpha)

    plt.xlim(xlims)
    plt.ylabel(label)
    plt.yticks([0,1])
    if not xaxis :
        plt.xticks([])

def plot_raw_layers(sim) :

    # open the plot window (sizes in figsize are in inches)
    f = plt.figure("BASAL GANGLIA-CORTEX SIMULATION EFP",figsize=([10,6]),facecolor='white')

    rows = 6    # we have 6 rows in our figure
    row = 0    # start the row counter
    for area in np.hstack(("DA", sim.SELECTED_META_AREAS )) :

        data = sim.raw_df[sim.raw_df.AREA==area].iloc[:,1:].as_matrix().ravel()
        plot_row_gs(data, row, xaxis=False, label=area)
        row +=1

def plot_ctx_channels(sim) :

    # open the plot window (sizes in figsize are in inches)
    f = plt.figure("CHANNELS",figsize=([10,6]),facecolor='white')

    rows = 10
    cols = (sim.TRIALS-1)/10 +1
    stime = sim.INNER_WINDOW
    gs = gridspec.GridSpec(rows, cols)

    xlims =[-50,stime+50]
    ylims = [-0.5,4.5]
    linewidth = 2.0    # width of the plot line
    plotalpha = 0.8    # alpha color of the line
    fillalpha = 0.1    # alpha color of the filled area

    for win in range(sim.TRIALS-1) :
        win_data = sim.df[(sim.df.AREA=="CTX") & (sim.df.WIN==win) ].iloc[:,5:-1].as_matrix()

        ax = f.add_subplot(gs[int(win%10),int(win/10)])
        ax.plot(win_data.T, linewidth=linewidth, alpha=plotalpha)
        ax.set_xlim(xlims)
        ax.set_ylim(ylims)
        ax.set_axis_off()

# we define a general plot function for a single row
def plot_row_gs(data, row, xaxis=True, label="layer", color="black") :

    stime = data.shape[0]

    gs = gridspec.GridSpec(6, 20 )

    xlims =[250,stime+50] # limits on the x axis

    mmax = 1
    mmin =  .5
    ylims = [-0.5,4.5] # limits on the y axis

    linewidth = 2.0    # width of the plot line
    plotalpha = 0.8    # alpha color of the line
    fillalpha = 0.1    # alpha color of the filled area

    plt.subplot(gs[row,:2])    # plot within the subplot window
    plt.axis("off")
    plt.text(.1,.2,label,fontsize=11)

    plt.subplot(gs[row,2:])    # plot within the subplot window

    y = data
    x = np.arange(stime)

    # plot the line
    plt.plot(y, color=color, linewidth=linewidth, alpha=plotalpha)

    plt.axis("off")
    plt.xlim(xlims)
    plt.ylim(ylims)
    plt.ylabel(label)
    plt.yticks([])
    plt.xticks([])


from flask import Flask, request, jsonify
from flask_cors import CORS

import logging

from custom_exceptions.reimbursement_exceptions import NegativeValueReimbursementRequestException, \
    NonNumericValueReimbursementRequestException, NonUpdatedStatusException
from custom_exceptions.user_exceptions import DuplicateCreateUserNameException, DuplicateUpdateUserNameException
from data_access_layer.implementation_classes.reimbursement_postgres_dao import ReimbursementPostgresDAO
from data_access_layer.implementation_classes.user_postgres_dao import UserPostgresDAO
from entities.reimbursement import Reimbursement
from entities.user import User
from service_layer.implementation_services.reimbursement_postgres_service import ReimbursementPostgresService
from service_layer.implementation_services.user_postgres_service import UserPostgresService

logging.basicConfig(filename="records.log", level=logging.DEBUG, format=f"%(asctime)s %(levelname)s %(message)s")
app: Flask = Flask(__name__)
CORS(app)

reimbursement_dao = ReimbursementPostgresDAO()
reimbursement_service = ReimbursementPostgresService(reimbursement_dao)
user_dao = UserPostgresDAO()
user_service = UserPostgresService(user_dao)

@app.get("/")
def landing_page():
    return "This is the landing page"

# Reimbursement
@app.post("/reimbursement")
def create_reimbursement():
    try:
        reimbursement_data = request.get_json()
        new_reimbursement = Reimbursement(
            0,
            int(reimbursement_data["userId"]),
            reimbursement_data["expenseName"],
            float(reimbursement_data["expenseAmount"]),
            reimbursement_data["expenseDetail"],
            reimbursement_data["status"],
            reimbursement_data["userComment"]
        )
        reimbursement_to_return = reimbursement_service.service_create_reimbursement(new_reimbursement)
        reimbursement_as_dictionary = reimbursement_to_return.create_reimbursement_dictionary()
        account_as_json = jsonify(reimbursement_as_dictionary)
        return account_as_json, 200
    except NegativeValueReimbursementRequestException as e:
        exception_dictionary = {"message": str(e)}
        exception_json = jsonify(exception_dictionary)
        return exception_json, 400
    except NonNumericValueReimbursementRequestException as e:
        exception_dictionary = {"message": str(e)}
        exception_json = jsonify(exception_dictionary)
        return exception_json, 400

@app.get("/reimbursement/<request_id>")
def get_reimbursements_by_request_id(request_id: str):
    result = reimbursement_service.service_get_reimbursements_by_request_id(int(request_id))
    result_as_dictionary = result.create_reimbursement_dictionary()
    account_as_json = jsonify(result_as_dictionary)
    return account_as_json

@app.get("/reimbursement/user/<user_id>")
def get_all_reimbursements_by_employee_id(user_id: str):
    reimbursements_as_reimbursements = reimbursement_service.service_get_all_reimbursements_by_employee_id(int(user_id))
    reimbursements_as_dictionary = []
    for reimbursements in reimbursements_as_reimbursements:
        dictionary_reimbursement = reimbursements.create_reimbursement_dictionary()
        reimbursements_as_dictionary.append(dictionary_reimbursement)
    return jsonify(reimbursements_as_dictionary)

@app.get("/reimbursement")
def get_all_reimbursements():
    reimbursements_as_reimbursements = reimbursement_service.service_get_all_reimbursements()
    reimbursements_as_dictionary = []
    for reimbursements in reimbursements_as_reimbursements:
        dictionary_reimbursement = reimbursements.create_reimbursement_dictionary()
        reimbursements_as_dictionary.append(dictionary_reimbursement)
    return jsonify(reimbursements_as_dictionary)

@app.patch("/reimbursement/<request_id>")
def update_reimbursement(request_id: str):
    try:
        body = request.get_json()
        update_info = Reimbursement(
            int(request_id),
            int(body["userId"]),
            body["expenseName"],
            float(body["expenseAmount"]),
            body["expenseDetail"],
            body["status"],
            body["userComment"]
        )
        updated_reimbursement = reimbursement_service.service_update_reimbursements_by_id(update_info)
        updated_reimbursement_as_dictionary = updated_reimbursement.create_reimbursement_dictionary()
        return jsonify(updated_reimbursement_as_dictionary), 200
    except NonUpdatedStatusException as e:
        error_message = {"errorMessage": str(e)}
        return jsonify(error_message), 400

@app.delete("/reimbursement/<request_id>")
def delete_reimbursement_by_request_id(request_id: str):
    result = reimbursement_service.service_delete_reimbursement_by_request_id(int(request_id))
    if result:
        return "Reimbursement with ID {} was deleted successfully".format(request_id)
    else:
        return "Something went wrong: Reimbursement with ID {} was not deleted".format(request_id)

# User
# LOGGING IN
@app.post("/login")
def login():
    body = request.get_json()
    login_credentials = (body["userName"], body["userPassword"], body["userRole"])
    validated = user_service.service_login_into_account(login_credentials[0], login_credentials[1], login_credentials[2])
    if validated:
        message = {"validated": True}
        return jsonify(message), 200
    else:
        message = {"validated": False}
        return jsonify(message), 400

@app.post("/user")
def create_user():
    try:
        body = request.get_json()
        new_user = User(
            body["firstName"],
            body["lastName"],
            body["userRole"],
            0,
            body["userName"],
            body["userPassword"]
        )
        created_user = user_service.service_create_user(new_user)
        created_user_as_dictionary = created_user.create_user_dictionary()
        return jsonify(created_user_as_dictionary), 200
    except DuplicateCreateUserNameException as e:
        error_message = {"errorMessage": str(e)}
        return jsonify(error_message), 400

@app.get("/user/<user_id>")
def get_user_by_id(user_id: str):
    user = user_service.service_get_user_by_id(int(user_id))
    user_as_dictionary = user.create_user_dictionary()
    return jsonify(user_as_dictionary), 200

@app.get("/user")
def get_all_user_by_id():
    users = user_service.service_get_all_user_by_id()
    users_as_dictionaries = []
    for user in users:
        dictionary_user = user.create_user_dictionary()
        users_as_dictionaries.append(dictionary_user)
    return jsonify(users_as_dictionaries), 200

@app.patch("/user/<user_id>")
def update_user(user_id: str):
    try:
        body = request.get_json()
        update_info = User(
            body["firstName"],
            body["lastName"],
            body["userRole"],
            int(user_id),
            body["userName"],
            body["userPassword"]
        )
        updated_user = user_service.service_update_user_information(update_info)
        updated_user_as_dictionary = updated_user.create_user_dictionary()
        return jsonify(updated_user_as_dictionary), 200
    except DuplicateUpdateUserNameException as e:
        return str(e), 400

@app.delete("/user/<user_id>")
def delete_user(user_id: str):
    result = user_service.service_delete_user_by_id(int(user_id))
    if result:
        return f"User with ID {user_id} was deleted successfully"
    else:
        return f"Something went wrong. User with ID {user_id} was not deleted"

app.run()


"""
This is how you want to use the logging module in a small script.

NOTES:
- if you don"t configure logging through other means, or call
"basicConfig" you will get warnings when you try to log (no handlers).
- if you dont pass the "level" parameter to "basicConfig" you
will get the default level which is WARNING (pretty good).
- don"t do "logger.setLevel". This is contrary to logging philosophy.
"""

import logging

logger = logging.getLogger(__name__)
logger.setLevel(logging.DEBUG)

logger.debug("before")
logger.info("before")
logger.warning("before")
logger.error("before")

# logging.basicConfig(level=logging.WARNING)
logging.basicConfig()

logger.debug("after")
logger.info("after")
logger.warning("after")
logger.error("after")


from django.shortcuts import render, get_object_or_404
from .models import Category, Dish

"""
To display the menu, a view is created to
list all dishes or filter dishes by a given category
"""

#
def dish_list(request, category_slug = None):
    """
    """
    category    = None
    # List of all the categories (available in the database)
    categories  = Category.objects.all()
    # List of all the dishes (available in the database)
    dishes      = Dish.objects.all()
    #
    if category_slug:
        #
        category    = get_object_or_404(Category, slug = category_slug)
        #
        dishes      = dishes.filter(category = category)
    #
    template_name   = "menu/dish/list.html"
    #
    context         = {"category":category, "categories":categories, "dishes":dishes}
    #
    return render(request, template_name, context)


from langchain.agents import Tool
from langchain.chains import RetrievalQA
from langchain.embeddings.openai import OpenAIEmbeddings
from langchain.llms import OpenAI
from langchain.text_splitter import CharacterTextSplitter
from langchain.vectorstores import Chroma

def setup_knowledge_base(product_catalog: str = None):
    """
    We assume that the product catalog is simply a text string.
    """
    # load product catalog
    with open(product_catalog, "r") as f:
        product_catalog = f.read()

    text_splitter = CharacterTextSplitter(chunk_size=10, chunk_overlap=0)
    texts = text_splitter.split_text(product_catalog)

    llm = OpenAI(temperature=0)
    embeddings = OpenAIEmbeddings()
    docsearch = Chroma.from_texts(
        texts, embeddings, collection_name="product-knowledge-base"
    )

    knowledge_base = RetrievalQA.from_chain_type(
        llm=llm, chain_type="stuff", retriever=docsearch.as_retriever()
    )
    return knowledge_base

def get_tools(knowledge_base):
    # we only use one tool for now, but this is highly extensible!
    tools = [
        Tool(
            name="ProductSearch",
            func=knowledge_base.run,
            description="useful for when you need to answer questions about product information",
        )
    ]

    return tools


import shutil
import tempfile
from django.conf import settings
from django.contrib.auth import get_user_model
from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import Client, TestCase, override_settings
from django.urls import reverse

from posts.models import Group, Post, Comment

User = get_user_model()

TEMP_MEDIA_ROOT = tempfile.mkdtemp(dir=settings.BASE_DIR)

@override_settings(MEDIA_ROOT=TEMP_MEDIA_ROOT)
class PostCreateEditFormTests(TestCase):
    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.user = User.objects.create_user(username='test_author')
        cls.group = Group.objects.create(
            title='TestGroup1',
            slug='TestGroup1',
            description='TestGroup1'
        )
        cls.test_post = Post.objects.create(
            text='Тест №0',
            group=cls.group,
            author=cls.user
        )
        cls.test_post_2 = Post.objects.create(
            text='Тест №0_1',
            group=cls.group,
            author=cls.user
        )
        cls.test_comment = Comment.objects.create(
            text='Тестовый комментарий №0 к тестовому посту',
            author=cls.user,
            post=cls.test_post
        )

    @classmethod
    def tearDownClass(cls):
        super().tearDownClass()
        shutil.rmtree(TEMP_MEDIA_ROOT, ignore_errors=True)

    def setUp(self):
        self.user_1_client = Client()
        self.user_1_client.force_login(PostCreateEditFormTests.user)

    def test_create_post(self):
        """
        Проверим формы создания поста.
        """
        post_count = Post.objects.count()
        form_data = {
            'text': 'Тест №1',
            'group': PostCreateEditFormTests.group.pk
        }
        response = self.user_1_client.post(
            reverse(
                'posts:post_create'
            ),
            data=form_data,
            follow=True
        )
        self.assertRedirects(
            response,
            reverse(
                'posts:profile',
                kwargs={'username': self.user}
            )
        )
        self.assertEqual(
            Post.objects.count(),
            post_count + 1
        )
        self.assertTrue(
            Post.objects.filter(
                text=form_data['text'],
                group=form_data['group'],
                author=PostCreateEditFormTests.user
            ).exists()
        )

    def test_edit_post(self):
        """
        Проверим формы редактирования поста.
        """
        post_count = Post.objects.count()
        form_data = {
            'text': 'Тест №2',
            'group': PostCreateEditFormTests.group.pk
        }
        response = self.user_1_client.post(
            reverse(
                'posts:post_edit',
                kwargs={'post_id': PostCreateEditFormTests.test_post.id}
            ),
            data=form_data,
            follow=True
        )
        self.assertRedirects(
            response,
            reverse(
                'posts:post_detail',
                kwargs={'post_id': PostCreateEditFormTests.test_post.id}
            )
        )
        self.assertEqual(
            Post.objects.count(),
            post_count
        )
        self.assertTrue(
            Post.objects.filter(
                text=form_data['text'],
                group=form_data['group'],
                author=PostCreateEditFormTests.user
            ).exists()
        )

    def test_image_form_context(self):
        """
        Проверим, что в базе данных создаётся
        корректный пост с картинкой.
        """
        post_count = Post.objects.count()
        small_gif = (
            b'\x47\x49\x46\x38\x39\x61\x02\x00'
            b'\x01\x00\x80\x00\x00\x00\x00\x00'
            b'\xFF\xFF\xFF\x21\xF9\x04\x00\x00'
            b'\x00\x00\x00\x2C\x00\x00\x00\x00'
            b'\x02\x00\x01\x00\x00\x02\x02\x0C'
            b'\x0A\x00\x3B'
        )
        uploaded = SimpleUploadedFile(
            name='small.gif',
            content=small_gif,
            content_type='image/gif'
        )
        form_data = {
            'text': 'Тест №3',
            'group': PostCreateEditFormTests.group.pk,
            'image': uploaded
        }
        self.user_1_client.post(
            reverse(
                'posts:post_create'
            ),
            data=form_data,
            follow=True
        )
        self.assertEqual(
            Post.objects.count(),
            post_count + 1
        )
        self.assertTrue(
            Post.objects.filter(
                text=form_data['text'],
                group=form_data['group'],
                author=PostCreateEditFormTests.user,
                image='posts/small.gif'
            ).exists()
        )

    def test_comment_create(self):
        """
        Проверим, что при что при создании комментария, он начинает
        отображаться на странице post_detail.
        """
        comment_count = Comment.objects.count()
        form_data = {
            'text': 'Тестовый комментарий №1 к тестовому посту',
        }
        self.user_1_client.post(
            reverse(
                'posts:add_comment',
                kwargs={'post_id': PostCreateEditFormTests.test_post.id}
            ),
            data=form_data,
            follow=False
        )
        self.assertEqual(comment_count + 1, Comment.objects.count())
        self.assertTrue(
            Comment.objects.filter(
                post=PostCreateEditFormTests.test_post,
                text=form_data['text'],
                author=PostCreateEditFormTests.user
            ).exists()
        )


import logging
import time
from typing import Dict

import pika

def rabbit_mq_heartbeat():
    while True:
        try:
            connection = pika.BlockingConnection(
                pika.ConnectionParameters(host="rabbitmq")
            )
            return connection
        except pika.exceptions.AMQPConnectionError:
            print("AMQPConnectionError trying again")
            time.sleep(5)
            continue

class MessageQueue:
    """
    Class to configure message queue
    """

    def __init__(self) -> None:
        self.connection = rabbit_mq_heartbeat()

    def publish(self, payload: Dict) -> Dict:
        logging.info("Connected to rabbitmq server......")
        channel = self.connection.channel()
        channel.queue_declare(queue="checkin_queue", durable=True)
        channel.basic_publish(
            exchange="",
            routing_key="checkin_queue",
            body=payload,
            properties=pika.BasicProperties(
                delivery_mode=2,  # make message persistent
            ),
        )


"""empty message

Revision ID: dca22f874919
Revises: 2525683b79b9
Create Date: 2018-04-11 10:15:56.444913

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = 'dca22f874919'
down_revision = '2525683b79b9'
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('room', sa.Column('building', sa.String(), nullable=True))
    op.add_column('room', sa.Column('campus', sa.String(), nullable=True))
    op.add_column('room', sa.Column('capacity', sa.Integer(), nullable=True))
    op.add_column('room', sa.Column('floor', sa.Integer(), nullable=True))
    op.add_column('room', sa.Column('group', sa.String(), nullable=True))
    op.add_column('room', sa.Column('no', sa.Integer(), nullable=True))
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('room', 'no')
    op.drop_column('room', 'group')
    op.drop_column('room', 'floor')
    op.drop_column('room', 'capacity')
    op.drop_column('room', 'campus')
    op.drop_column('room', 'building')
    # ### end Alembic commands ###


from collections import deque

#Start(sx, sy)から各頂点への最短距離を求める

def bfs(sx, sy):
    cnt = 0
    f_inf = float('inf')
    dist = [[f_inf] * m for _ in range(n)]

    dx = [1, 0, -1, 0]
    dy = [0, 1, 0, -1]

    #Start地点を0にする
    que = deque([])
    que.append((sx, sy))
    dist[sx][sy] = 0

    while que:
        p = que.popleft()

        for i in range(4):
            #移動した点を(nx, ny)とする
            nx = p[0] + dx[i]
            ny = p[1] + dy[i]

            #移動可能かと既に訪れたかの判定
            #dist[nx][ny] != f_infなら既に訪れた
            if n > nx >= 0 and \
               m > ny >= 0 and \
               s[nx][ny] != '#' and \
               dist[nx][ny] == f_inf:
                que.append((nx, ny))
                dist[nx][ny] = dist[p[0]][p[1]] + 1
                cnt = dist[nx][ny]

    return cnt

n, m = map(int, input().split())
s = [input() for _ in range(n)]

ans = 0
for i in range(n):
    for j in range(m):
        if s[i][j] == '#':
            continue
        ans = max(ans, bfs(i, j))
print(ans)

#n = 3
#m = 5
#s =['...#.', '.#.#.', '.#...']


from django.http import HttpResponse
from django.shortcuts import render_to_response
from django.contrib.auth.decorators import login_required
from helpers import render_to_json, jsonResponse
from django.forms.models import modelformset_factory
from django.template import RequestContext
from models import PaymentRequest

@login_required
@render_to_json
def get(req, payment_request_id):
    if payment_request_id:
        payment_request = PaymentRequest.objects.get(id=payment_request_id)
        return payment_request.serialize()
    else:
        return [payment_request.serialize()
                for payment_request in PaymentRequest.objects.all()]

@login_required
def create(req):
    PaymentRequestFormSet = modelformset_factory(PaymentRequest)
    if req.method == 'POST':
        formset = PaymentRequestFormSet(req.POST)
        if formset.is_valid():
            payment_request = formset.save()
            # do something.
            return jsonResponse(payment_request[0].serialize())
    else:
        formset = PaymentRequestFormSet(queryset=PaymentRequest.objects.none())
    return render_to_response("payment_request.html",
            {"formset": formset},
            context_instance=RequestContext(req))

@login_required
@render_to_json
def update(req, payment_request_id):
    pass

@login_required
@render_to_json
def delete(req, payment_request_id):
    PaymentRequest.objects.get(id=payment_request_id).delete()
    return {'success': True}


# results.py
from collections.abc import (
    MutableMapping,
    Mapping,
    MutableSequence,
    Iterator,
    Sequence,
    Container,
)
import pprint
from typing import Tuple, Any, Dict, Set, List

str_type: Tuple[type, ...] = (str, bytes)
_generator_type = type((_ for _ in ()))

class _ParseResultsWithOffset:
    tup: Tuple["ParseResults", int]
    __slots__ = ["tup"]

    def __init__(self, p1: "ParseResults", p2: int):
        self.tup: Tuple[ParseResults, int] = (p1, p2)

    def __getitem__(self, i):
        return self.tup[i]

    def __getstate__(self):
        return self.tup

    def __setstate__(self, *args):
        self.tup = args[0]

class ParseResults:
    """Structured parse results, to provide multiple means of access to
    the parsed data:

    - as a list (``len(results)``)
    - by list index (``results[0], results[1]``, etc.)
    - by attribute (``results.<results_name>`` - see :class:`ParserElement.set_results_name`)

    Example::

        integer = Word(nums)
        date_str = (integer.set_results_name("year") + '/'
                    + integer.set_results_name("month") + '/'
                    + integer.set_results_name("day"))
        # equivalent form:
        # date_str = (integer("year") + '/'
        #             + integer("month") + '/'
        #             + integer("day"))

        # parse_string returns a ParseResults object
        result = date_str.parse_string("1999/12/31")

        def test(s, fn=repr):
            print(f"{s} -> {fn(eval(s))}")
        test("list(result)")
        test("result[0]")
        test("result['month']")
        test("result.day")
        test("'month' in result")
        test("'minutes' in result")
        test("result.dump()", str)

    prints::

        list(result) -> ['1999', '/', '12', '/', '31']
        result[0] -> '1999'
        result['month'] -> '12'
        result.day -> '31'
        'month' in result -> True
        'minutes' in result -> False
        result.dump() -> ['1999', '/', '12', '/', '31']
        - day: '31'
        - month: '12'
        - year: '1999'
    """

    _null_values: Tuple[Any, ...] = (None, [], ())

    _name: str
    _parent: "ParseResults"
    _all_names: Set[str]
    _modal: bool
    _toklist: List[Any]
    _tokdict: Dict[str, Any]

    __slots__ = (
        "_name",
        "_parent",
        "_all_names",
        "_modal",
        "_toklist",
        "_tokdict",
    )

    class List(list):
        """
        Simple wrapper class to distinguish parsed list results that should be preserved
        as actual Python lists, instead of being converted to :class:`ParseResults`::

            LBRACK, RBRACK = map(pp.Suppress, "[]")
            element = pp.Forward()
            item = ppc.integer
            element_list = LBRACK + pp.DelimitedList(element) + RBRACK

            # add parse actions to convert from ParseResults to actual Python collection types
            def as_python_list(t):
                return pp.ParseResults.List(t.as_list())
            element_list.add_parse_action(as_python_list)

            element <<= item | element_list

            element.run_tests('''
                100
                [2,3,4]
                [[2, 1],3,4]
                [(2, 1),3,4]
                (2,3,4)
                ''', post_parse=lambda s, r: (r[0], type(r[0])))

        prints::

            100
            (100, <class 'int'>)

            [2,3,4]
            ([2, 3, 4], <class 'list'>)

            [[2, 1],3,4]
            ([[2, 1], 3, 4], <class 'list'>)

        (Used internally by :class:`Group` when `aslist=True`.)
        """

        def __new__(cls, contained=None):
            if contained is None:
                contained = []

            if not isinstance(contained, list):
                raise TypeError(
                    f"{cls.__name__} may only be constructed with a list, not {type(contained).__name__}"
                )

            return list.__new__(cls)

    def __new__(cls, toklist=None, name=None, **kwargs):
        if isinstance(toklist, ParseResults):
            return toklist
        self = object.__new__(cls)
        self._name = None
        self._parent = None
        self._all_names = set()

        if toklist is None:
            self._toklist = []
        elif isinstance(toklist, (list, _generator_type)):
            self._toklist = (
                [toklist[:]]
                if isinstance(toklist, ParseResults.List)
                else list(toklist)
            )
        else:
            self._toklist = [toklist]
        self._tokdict = dict()
        return self

    # Performance tuning: we construct a *lot* of these, so keep this
    # constructor as small and fast as possible
    def __init__(
        self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance
    ):
        self._tokdict: Dict[str, _ParseResultsWithOffset]
        self._modal = modal
        if name is not None and name != "":
            if isinstance(name, int):
                name = str(name)
            if not modal:
                self._all_names = {name}
            self._name = name
            if toklist not in self._null_values:
                if isinstance(toklist, (str_type, type)):
                    toklist = [toklist]
                if asList:
                    if isinstance(toklist, ParseResults):
                        self[name] = _ParseResultsWithOffset(
                            ParseResults(toklist._toklist), 0
                        )
                    else:
                        self[name] = _ParseResultsWithOffset(
                            ParseResults(toklist[0]), 0
                        )
                    self[name]._name = name
                else:
                    try:
                        self[name] = toklist[0]
                    except (KeyError, TypeError, IndexError):
                        if toklist is not self:
                            self[name] = toklist
                        else:
                            self._name = name

    def __getitem__(self, i):
        if isinstance(i, (int, slice)):
            return self._toklist[i]
        else:
            if i not in self._all_names:
                return self._tokdict[i][-1][0]
            else:
                return ParseResults([v[0] for v in self._tokdict[i]])

    def __setitem__(self, k, v, isinstance=isinstance):
        if isinstance(v, _ParseResultsWithOffset):
            self._tokdict[k] = self._tokdict.get(k, list()) + [v]
            sub = v[0]
        elif isinstance(k, (int, slice)):
            self._toklist[k] = v
            sub = v
        else:
            self._tokdict[k] = self._tokdict.get(k, list()) + [
                _ParseResultsWithOffset(v, 0)
            ]
            sub = v
        if isinstance(sub, ParseResults):
            sub._parent = self

    def __delitem__(self, i):
        if isinstance(i, (int, slice)):
            mylen = len(self._toklist)
            del self._toklist[i]

            # convert int to slice
            if isinstance(i, int):
                if i < 0:
                    i += mylen
                i = slice(i, i + 1)
            # get removed indices
            removed = list(range(*i.indices(mylen)))
            removed.reverse()
            # fixup indices in token dictionary
            for name, occurrences in self._tokdict.items():
                for j in removed:
                    for k, (value, position) in enumerate(occurrences):
                        occurrences[k] = _ParseResultsWithOffset(
                            value, position - (position > j)
                        )
        else:
            del self._tokdict[i]

    def __contains__(self, k) -> bool:
        return k in self._tokdict

    def __len__(self) -> int:
        return len(self._toklist)

    def __bool__(self) -> bool:
        return not not (self._toklist or self._tokdict)

    def __iter__(self) -> Iterator:
        return iter(self._toklist)

    def __reversed__(self) -> Iterator:
        return iter(self._toklist[::-1])

    def keys(self):
        return iter(self._tokdict)

    def values(self):
        return (self[k] for k in self.keys())

    def items(self):
        return ((k, self[k]) for k in self.keys())

    def haskeys(self) -> bool:
        """
        Since ``keys()`` returns an iterator, this method is helpful in bypassing
        code that looks for the existence of any defined results names."""
        return not not self._tokdict

    def pop(self, *args, **kwargs):
        """
        Removes and returns item at specified index (default= ``last``).
        Supports both ``list`` and ``dict`` semantics for ``pop()``. If
        passed no argument or an integer argument, it will use ``list``
        semantics and pop tokens from the list of parsed tokens. If passed
        a non-integer argument (most likely a string), it will use ``dict``
        semantics and pop the corresponding value from any defined results
        names. A second default return value argument is supported, just as in
        ``dict.pop()``.

        Example::

            numlist = Word(nums)[...]
            print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321']

            def remove_first(tokens):
                tokens.pop(0)
            numlist.add_parse_action(remove_first)
            print(numlist.parse_string("0 123 321")) # -> ['123', '321']

            label = Word(alphas)
            patt = label("LABEL") + Word(nums)[1, ...]
            print(patt.parse_string("AAB 123 321").dump())

            # Use pop() in a parse action to remove named result (note that corresponding value is not
            # removed from list form of results)
            def remove_LABEL(tokens):
                tokens.pop("LABEL")
                return tokens
            patt.add_parse_action(remove_LABEL)
            print(patt.parse_string("AAB 123 321").dump())

        prints::

            ['AAB', '123', '321']
            - LABEL: 'AAB'

            ['AAB', '123', '321']
        """
        if not args:
            args = [-1]
        for k, v in kwargs.items():
            if k == "default":
                args = (args[0], v)
            else:
                raise TypeError(f"pop() got an unexpected keyword argument {k!r}")
        if isinstance(args[0], int) or len(args) == 1 or args[0] in self:
            index = args[0]
            ret = self[index]
            del self[index]
            return ret
        else:
            defaultvalue = args[1]
            return defaultvalue

    def get(self, key, default_value=None):
        """
        Returns named result matching the given key, or if there is no
        such name, then returns the given ``default_value`` or ``None`` if no
        ``default_value`` is specified.

        Similar to ``dict.get()``.

        Example::

            integer = Word(nums)
            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")

            result = date_str.parse_string("1999/12/31")
            print(result.get("year")) # -> '1999'
            print(result.get("hour", "not specified")) # -> 'not specified'
            print(result.get("hour")) # -> None
        """
        if key in self:
            return self[key]
        else:
            return default_value

    def insert(self, index, ins_string):
        """
        Inserts new element at location index in the list of parsed tokens.

        Similar to ``list.insert()``.

        Example::

            numlist = Word(nums)[...]
            print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321']

            # use a parse action to insert the parse location in the front of the parsed results
            def insert_locn(locn, tokens):
                tokens.insert(0, locn)
            numlist.add_parse_action(insert_locn)
            print(numlist.parse_string("0 123 321")) # -> [0, '0', '123', '321']
        """
        self._toklist.insert(index, ins_string)
        # fixup indices in token dictionary
        for name, occurrences in self._tokdict.items():
            for k, (value, position) in enumerate(occurrences):
                occurrences[k] = _ParseResultsWithOffset(
                    value, position + (position > index)
                )

    def append(self, item):
        """
        Add single element to end of ``ParseResults`` list of elements.

        Example::

            numlist = Word(nums)[...]
            print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321']

            # use a parse action to compute the sum of the parsed integers, and add it to the end
            def append_sum(tokens):
                tokens.append(sum(map(int, tokens)))
            numlist.add_parse_action(append_sum)
            print(numlist.parse_string("0 123 321")) # -> ['0', '123', '321', 444]
        """
        self._toklist.append(item)

    def extend(self, itemseq):
        """
        Add sequence of elements to end of ``ParseResults`` list of elements.

        Example::

            patt = Word(alphas)[1, ...]

            # use a parse action to append the reverse of the matched strings, to make a palindrome
            def make_palindrome(tokens):
                tokens.extend(reversed([t[::-1] for t in tokens]))
                return ''.join(tokens)
            patt.add_parse_action(make_palindrome)
            print(patt.parse_string("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl'
        """
        if isinstance(itemseq, ParseResults):
            self.__iadd__(itemseq)
        else:
            self._toklist.extend(itemseq)

    def clear(self):
        """
        Clear all elements and results names.
        """
        del self._toklist[:]
        self._tokdict.clear()

    def __getattr__(self, name):
        try:
            return self[name]
        except KeyError:
            if name.startswith("__"):
                raise AttributeError(name)
            return ""

    def __add__(self, other: "ParseResults") -> "ParseResults":
        ret = self.copy()
        ret += other
        return ret

    def __iadd__(self, other: "ParseResults") -> "ParseResults":
        if not other:
            return self

        if other._tokdict:
            offset = len(self._toklist)
            addoffset = lambda a: offset if a < 0 else a + offset
            otheritems = other._tokdict.items()
            otherdictitems = [
                (k, _ParseResultsWithOffset(v[0], addoffset(v[1])))
                for k, vlist in otheritems
                for v in vlist
            ]
            for k, v in otherdictitems:
                self[k] = v
                if isinstance(v[0], ParseResults):
                    v[0]._parent = self

        self._toklist += other._toklist
        self._all_names |= other._all_names
        return self

    def __radd__(self, other) -> "ParseResults":
        if isinstance(other, int) and other == 0:
            # useful for merging many ParseResults using sum() builtin
            return self.copy()
        else:
            # this may raise a TypeError - so be it
            return other + self

    def __repr__(self) -> str:
        return f"{type(self).__name__}({self._toklist!r}, {self.as_dict()})"

    def __str__(self) -> str:
        return (
            "["
            + ", ".join(
                [
                    str(i) if isinstance(i, ParseResults) else repr(i)
                    for i in self._toklist
                ]
            )
            + "]"
        )

    def _asStringList(self, sep=""):
        out = []
        for item in self._toklist:
            if out and sep:
                out.append(sep)
            if isinstance(item, ParseResults):
                out += item._asStringList()
            else:
                out.append(str(item))
        return out

    def as_list(self) -> list:
        """
        Returns the parse results as a nested list of matching tokens, all converted to strings.

        Example::

            patt = Word(alphas)[1, ...]
            result = patt.parse_string("sldkj lsdkj sldkj")
            # even though the result prints in string-like form, it is actually a pyparsing ParseResults
            print(type(result), result) # -> <class 'pyparsing.ParseResults'> ['sldkj', 'lsdkj', 'sldkj']

            # Use as_list() to create an actual list
            result_list = result.as_list()
            print(type(result_list), result_list) # -> <class 'list'> ['sldkj', 'lsdkj', 'sldkj']
        """
        return [
            res.as_list() if isinstance(res, ParseResults) else res
            for res in self._toklist
        ]

    def as_dict(self) -> dict:
        """
        Returns the named parse results as a nested dictionary.

        Example::

            integer = Word(nums)
            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")

            result = date_str.parse_string('12/31/1999')
            print(type(result), repr(result)) # -> <class 'pyparsing.ParseResults'> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]})

            result_dict = result.as_dict()
            print(type(result_dict), repr(result_dict)) # -> <class 'dict'> {'day': '1999', 'year': '12', 'month': '31'}

            # even though a ParseResults supports dict-like access, sometime you just need to have a dict
            import json
            print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable
            print(json.dumps(result.as_dict())) # -> {"month": "31", "day": "1999", "year": "12"}
        """

        def to_item(obj):
            if isinstance(obj, ParseResults):
                return obj.as_dict() if obj.haskeys() else [to_item(v) for v in obj]
            else:
                return obj

        return dict((k, to_item(v)) for k, v in self.items())

    def copy(self) -> "ParseResults":
        """
        Returns a new shallow copy of a :class:`ParseResults` object. `ParseResults`
        items contained within the source are shared with the copy. Use
        :class:`ParseResults.deepcopy()` to create a copy with its own separate
        content values.
        """
        ret = ParseResults(self._toklist)
        ret._tokdict = self._tokdict.copy()
        ret._parent = self._parent
        ret._all_names |= self._all_names
        ret._name = self._name
        return ret

    def deepcopy(self) -> "ParseResults":
        """
        Returns a new deep copy of a :class:`ParseResults` object.
        """
        ret = self.copy()
        # replace values with copies if they are of known mutable types
        for i, obj in enumerate(self._toklist):
            if isinstance(obj, ParseResults):
                self._toklist[i] = obj.deepcopy()
            elif isinstance(obj, (str, bytes)):
                pass
            elif isinstance(obj, MutableMapping):
                self._toklist[i] = dest = type(obj)()
                for k, v in obj.items():
                    dest[k] = v.deepcopy() if isinstance(v, ParseResults) else v
            elif isinstance(obj, Container):
                self._toklist[i] = type(obj)(
                    v.deepcopy() if isinstance(v, ParseResults) else v for v in obj
                )
        return ret

    def get_name(self):
        r"""
        Returns the results name for this token expression. Useful when several
        different expressions might match at a particular location.

        Example::

            integer = Word(nums)
            ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d")
            house_number_expr = Suppress('#') + Word(nums, alphanums)
            user_data = (Group(house_number_expr)("house_number")
                        | Group(ssn_expr)("ssn")
                        | Group(integer)("age"))
            user_info = user_data[1, ...]

            result = user_info.parse_string("22 111-22-3333 #221B")
            for item in result:
                print(item.get_name(), ':', item[0])

        prints::

            age : 22
            ssn : 111-22-3333
            house_number : 221B
        """
        if self._name:
            return self._name
        elif self._parent:
            par: "ParseResults" = self._parent
            parent_tokdict_items = par._tokdict.items()
            return next(
                (
                    k
                    for k, vlist in parent_tokdict_items
                    for v, loc in vlist
                    if v is self
                ),
                None,
            )
        elif (
            len(self) == 1
            and len(self._tokdict) == 1
            and next(iter(self._tokdict.values()))[0][1] in (0, -1)
        ):
            return next(iter(self._tokdict.keys()))
        else:
            return None

    def dump(self, indent="", full=True, include_list=True, _depth=0) -> str:
        """
        Diagnostic method for listing out the contents of
        a :class:`ParseResults`. Accepts an optional ``indent`` argument so
        that this string can be embedded in a nested display of other data.

        Example::

            integer = Word(nums)
            date_str = integer("year") + '/' + integer("month") + '/' + integer("day")

            result = date_str.parse_string('1999/12/31')
            print(result.dump())

        prints::

            ['1999', '/', '12', '/', '31']
            - day: '31'
            - month: '12'
            - year: '1999'
        """
        out = []
        NL = "\n"
        out.append(indent + str(self.as_list()) if include_list else "")

        if full:
            if self.haskeys():
                items = sorted((str(k), v) for k, v in self.items())
                for k, v in items:
                    if out:
                        out.append(NL)
                    out.append(f"{indent}{('  ' * _depth)}- {k}: ")
                    if isinstance(v, ParseResults):
                        if v:
                            out.append(
                                v.dump(
                                    indent=indent,
                                    full=full,
                                    include_list=include_list,
                                    _depth=_depth + 1,
                                )
                            )
                        else:
                            out.append(str(v))
                    else:
                        out.append(repr(v))
            if any(isinstance(vv, ParseResults) for vv in self):
                v = self
                for i, vv in enumerate(v):
                    if isinstance(vv, ParseResults):
                        out.append(
                            "\n{}{}[{}]:\n{}{}{}".format(
                                indent,
                                ("  " * (_depth)),
                                i,
                                indent,
                                ("  " * (_depth + 1)),
                                vv.dump(
                                    indent=indent,
                                    full=full,
                                    include_list=include_list,
                                    _depth=_depth + 1,
                                ),
                            )
                        )
                    else:
                        out.append(
                            "\n%s%s[%d]:\n%s%s%s"
                            % (
                                indent,
                                ("  " * (_depth)),
                                i,
                                indent,
                                ("  " * (_depth + 1)),
                                str(vv),
                            )
                        )

        return "".join(out)

    def pprint(self, *args, **kwargs):
        """
        Pretty-printer for parsed results as a list, using the
        `pprint <https://docs.python.org/3/library/pprint.html>`_ module.
        Accepts additional positional or keyword args as defined for
        `pprint.pprint <https://docs.python.org/3/library/pprint.html#pprint.pprint>`_ .

        Example::

            ident = Word(alphas, alphanums)
            num = Word(nums)
            func = Forward()
            term = ident | num | Group('(' + func + ')')
            func <<= ident + Group(Optional(DelimitedList(term)))
            result = func.parse_string("fna a,b,(fnb c,d,200),100")
            result.pprint(width=40)

        prints::

            ['fna',
             ['a',
              'b',
              ['(', 'fnb', ['c', 'd', '200'], ')'],
              '100']]
        """
        pprint.pprint(self.as_list(), *args, **kwargs)

    # add support for pickle protocol
    def __getstate__(self):
        return (
            self._toklist,
            (
                self._tokdict.copy(),
                None,
                self._all_names,
                self._name,
            ),
        )

    def __setstate__(self, state):
        self._toklist, (self._tokdict, par, inAccumNames, self._name) = state
        self._all_names = set(inAccumNames)
        self._parent = None

    def __getnewargs__(self):
        return self._toklist, self._name

    def __dir__(self):
        return dir(type(self)) + list(self.keys())

    @classmethod
    def from_dict(cls, other, name=None) -> "ParseResults":
        """
        Helper classmethod to construct a ``ParseResults`` from a ``dict``, preserving the
        name-value relations as results names. If an optional ``name`` argument is
        given, a nested ``ParseResults`` will be returned.
        """

        def is_iterable(obj):
            try:
                iter(obj)
            except Exception:
                return False
            # str's are iterable, but in pyparsing, we don't want to iterate over them
            else:
                return not isinstance(obj, str_type)

        ret = cls([])
        for k, v in other.items():
            if isinstance(v, Mapping):
                ret += cls.from_dict(v, name=k)
            else:
                ret += cls([v], name=k, asList=is_iterable(v))
        if name is not None:
            ret = cls([ret], name=name)
        return ret

    asList = as_list
    """Deprecated - use :class:`as_list`"""
    asDict = as_dict
    """Deprecated - use :class:`as_dict`"""
    getName = get_name
    """Deprecated - use :class:`get_name`"""

MutableMapping.register(ParseResults)
MutableSequence.register(ParseResults)


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

import mock
from completor import Completor, load_completer, get

class HelloCompleter(Completor):
    filetype = 'hello'

def test_disabled(vim_mod):
    com = HelloCompleter()
    vim_mod.vars = {'completor_disable_hello': 1}
    assert com.disabled
    vim_mod.vars = {'completor_disable_hello': [b'hello']}
    com.ft = 'hello'
    assert com.disabled
    vim_mod.vars = {}
    assert not com.disabled

def test_load(vim_mod, monkeypatch):
    vim_mod.eval = mock.Mock(return_value={})
    vim_mod.vars = {
        'completor_filetype_map': {
            b'python.django': b'python'
        }
    }
    assert get('python') is None
    c = load_completer(b'python', b'os.')
    assert c.input_data == 'os.'
    assert get('python') is c

    c = load_completer(b'python', b'#')
    assert c is get('common')

    c = load_completer(b'python.django', b'os.')
    assert c is get('python')

    vim_mod.current.buffer.options.update({
        'omnifunc': b'csscomplete#CompleteCSS'})
    vim_mod.vars = {
        'completor_css_omni_trigger': br'([\w-]+|@[\w-]*|[\w-]+:\s*[\w-]*)$'
    }
    assert load_completer(b'css', b'text') is get('omni')

def test_parse_config():
    h = HelloCompleter()
    args = h.parse_config('tests/test_config')
    assert args == ['-I/home/hello', '-x', '--std=c11', '-hello=world',
                    'abcd', '-a', '123']
    args = h.parse_config(['tests/invalid', 'tests/args',
                           'tests/tests_config'])
    assert args == ['-x', 'c', '-D/usr/lib/', '123']


from django.conf import settings
import requests

class StackOverflowMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        return self.get_response(request)

    def process_exception(self, request, exception):
        if settings.DEBUG:
            error = '{}: {}'.format(exception.__class__.__name__, exception)
            print(error)

            url = 'https://api.stackexchange.com/2.2/search'
            headers = { 'User-Agent': 'github.com/vitorfs/seot' }
            params = {
                'order': 'desc',
                'sort': 'votes',
                'site': 'stackoverflow',
                'pagesize': 3,
                'tagged': 'python;django',
                'intitle': error
            }

            r = requests.get(url=url, params=params, headers=headers)
            questions = r.json()

            print('')

            for question in questions['items']:
                print(question['title'])
                print(question['link'])
                print('')

        return None


import os
import re
from datetime import datetime
import pyodbc

class RecordLoader:
    def __init__(self,copy_target,target_metadata,mapped_target_columnnames_list,insert_method,max_row_per_batch):
        self.conn = pyodbc.connect(str(copy_target.conn_str))
        self.cursor = self.conn.cursor()
        self.target_metadata = target_metadata
        self.max_row_per_batch = max_row_per_batch
        self.quoted_mapped_target_columnnames_list = self.quote_columnnames_list(mapped_target_columnnames_list)
        self.insert_method = insert_method
        self.record_list = []
        self.param_marker = ""
        self.param_value_list = []

    def quote_columnnames_list(self,mapped_target_columnnames_list):
        return ['"{}"'.format(x) for x in mapped_target_columnnames_list]

    def add_record(self,record):
        if record:
            if self.insert_method == "prepared":
                for v in record:#row_param_value_list:
                    self.record_list.append(v)
            else:#reserved for batch
                self.record_list.append("(" + ",".join(record)+")")
        if self.insert_method == "prepared":
            batch_count = int(len(self.record_list)/len(self.quoted_mapped_target_columnnames_list))
        else:#reserved for batch
            batch_count = len(self.record_list)

        if(batch_count % self.max_row_per_batch == 0 or record == False):
            if len(self.record_list) > 0:
                if self.insert_method == "prepared":
                    if record:
                        _param_markers = self.gen_row_param_markers(len(self.quoted_mapped_target_columnnames_list),self.max_row_per_batch)
                    else:
                        _param_markers = self.gen_row_param_markers(len(self.quoted_mapped_target_columnnames_list),batch_count)
                    #print("----")
                    #print(_param_markers)
                    prepared_stmt = """INSERT INTO {}.{} ({}) VALUES {}
                                    """.format(self.target_metadata.schema_name,self.target_metadata.table_name,",".join(self.quoted_mapped_target_columnnames_list),_param_markers)
                    #print(prepared_stmt)
                    #print(self.record_list)

                    self.cursor.execute(prepared_stmt,self.record_list)
                    self.conn.commit()
                    self.record_list.clear()
                else:#reserved for batch
                    batch_stmt = """INSERT INTO {}.{} ({}) VALUES {}
                                """.format(self.target_metadata.schema_name,self.target_metadata.table_name,",".join(self.quoted_mapped_target_columnnames_list),",".join(self.record_list))

                    #print(batch_stmt)
                    # print(self.record_list)

                    try:
                        self.cursor.execute(batch_stmt)
                        self.conn.commit()
                        self.record_list.clear()
                    except Exception as e:
                        print(e)
                        print('failed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!')
                        cwd = os.getcwd()

                        timestamp = str(datetime.now())
                        timestamp = re.sub("[-:.]","",timestamp)
                        path = cwd + "\\dumps\\dump" + timestamp + ".txt"
                        print(path)
                        file = open(path,"w")
                        file.write(str(batch_stmt)+ '\n') #
                        quit()

    def gen_row_param_markers(self,num_col,num_row):
        param = "(" + ",".join("?"*num_col) + ")"
        params = []
        for i in range(num_row):
            params.append(param)
        return ",".join(params)

class Dump:
    """plain data dump"""
    def __init__(self,dirname,data, name=None):
        self.dirname = dirname
        self.data = data
        self.name = name
        #self.totext(dirname,data,name)
    def totext(self):
        timestamp = str(datetime.now())
        timestamp = re.sub("[-:.]","",timestamp)
        if self.name is not None:
            filename = "dump_" + self.name
        else:
            filename = "dump"
        path = os.path.join(self.dirname,filename + timestamp + ".txt")
        try:
            file = open(path,"w")
            if type(self.data) is list or type(self.data) is tuple:
                for row in self.data:
                    try:
                        file.write(str(row)+ '\n') #
                    except Exception as e:
                        print('warning! {} with reference to writing row {}.'.format(e,row))
            else:
                file.write(str(self.data))
        except Exception as e:
            print('warning! {} with reference to dumping object.'.format(e))
            pass

    def tocsv(self):
        timestamp = str(datetime.now())
        timestamp = re.sub("[-:.]","",timestamp)
        if self.name is not None:
            filename = "dump_" + self.name
        else:
            filename = "dump"
        path = os.path.join(self.dirname,filename + timestamp + ".csv")
        try:
            file = open(path,"w")
            if type(self.data) is list or type(self.data) is tuple:
                i = 0
                for row in self.data:
                    columnname_list = list(row.keys())
                    data_list = list(row.values())
                    try:
                        if i == 0: #columns and data
                            file.write(','.join(columnname_list) + '\n')
                            file.write(','.join(str(x) for x in data_list) + '\n')
                        if i > 0: #data only
                            file.write(','.join(str(x) for x in data_list) + '\n')
                    except Exception as e:
                        print('warning! {} with reference to writing row {}.'.format(e,row))

                    i += 1
            else:
                file.write(str(self.data))
        except Exception as e:
            print('warning! {} with reference to dumping object.'.format(e))
            pass


# -*- coding:UTF-8 -*-
import requests
import json

class DoubanSpider():
    def __init__(self):
        self.url = {
            "url_temp": "https://m.douban.com/rexxar/api/v2/subject_collection/tv_domestic/items?&start={}&count=18&loc_id=108288",

            "country": "us"}
        self.headers = {"Referer": "https://m.douban.com/tv/chinese",

                        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36"

                        }

    def parse_url(self, url):  # 发送请求，获取响应
        print(url)
        response = requests.get(url, headers=self.headers)
        return response.content.decode()

    def get_content_list(self, json_str):  # 提取数据

        dict_ret = json.loads(json_str)  # 转化为python字典对象
        content_list = dict_ret["subject_collection_items"]  # 通过字典的键得到相应的值，从而获取页面数据列表

        for a in content_list:
            print(a['title'])
        return content_list

    def save_content_list(self, content_list, country):  # 保存数据
        for content in content_list:
            with open('douban_my.txt', 'a', encoding='UTF-8') as f:
                content["country"] = country
                f.write(json.dumps(content, ensure_ascii=False))
                f.write('\n')
        print('保存成功')

    def run(self):  # 实现主要逻辑
        num = 0
        while True:
            # 1、获取第一页url
            start_url = self.url["url_temp"].format(num)
            # 2、发送请求，获取响应
            json_str = self.parse_url(start_url)
            # 3、提取数据
            content_list = self.get_content_list(json_str)
            # # 4、保存
            #self.save_content_list(content_list, self.url["country"])
            # 5、获取第二页url
            if len(content_list) < 18:  # 判断是否到了最后一页
                break
            num += 18

if __name__ == '__main__':
    doubanspider = DoubanSpider()
    doubanspider.run()


"""
This solution uses an iterative approach to solve the problem. It adds all the
nodes' value in reverse of the postorder, then reverse the list back when
returning.
"""
from typing import List

class Node:
    def __init__(self, val=None, children=None):
        self.val = val
        self.children = children

class Solution:
    def postorder(self, root: "Node") -> List[int]:
        # check if the tree is empty
        if not root:
            return []

        # create a list to store the answer
        lst = []
        # create a list that is used as a stack
        stack = [root]

        # add all the nodes' value in the reverse order of postorder
        while stack:
            # get the node
            node = stack.pop()

            # if the node has children, add them to the stack
            if node.children:
                stack.extend(node.children)

            # add the node's value to the list
            lst.append(node.val)

        # reverse the list to get the postorder traversal
        return lst[::-1]


import xarray as xr
from metpy.units import units
import metpy.calc as mpcalc
import numpy as np

def mask_below_terrain(spres,data,levs):
    '''
    Given a surface pressure, return data only above that pressure.

    Needs spres, a surface pressure (float)
    Needs data, a pint quantity array of temps/dew point/rh/whatever
    Needs levs, a pint quantity array of pressures
    '''
    above_ground = []
    for i in range(len(levs)):
        diff = levs[i]-spres
        if diff <0:
            above_ground.append(levs[i])
    pres_abv_ground = above_ground*units.hPa
    num_points_abv_ground = len(above_ground)
    data_abv_ground = data[-num_points_abv_ground:]
    return [data_abv_ground,pres_abv_ground]


# {"name":"%s","x":%f,"y":%f,"w":%f,"h":%f}
import json
import base64
import wget
import zipfile
from pyiotown import post
import os

num = 0
category = {}
annodict = {}
def make_label(file_name, label, bbox):
    img_file = open("./upload_data/coco2017/train2017/" + file_name , 'rb')
    message = '{"image":"'
    message += base64.b64encode(img_file.read()).decode('UTF-8')
    img_file.close()
    message += '","type":"jpg","labels":['
    first = True
    for box in bbox:
        if first:
            first = False
        else:
            message += ','
        message += '{"name":"%s","x":%f,"y":%f,"w":%f,"h":%f}' % (label,box[0],box[1],box[2],box[3])
    message += ']}'
    return message

def sendToIoTown(json_data, url, token, label):
    global category, annodict, num
    #init category
    for cat in json_data['categories']:
        category[cat['name']] = cat['id']
    if label not in category:
        print("coco 2017 has no label [",label,"]")
        exit()

    #Save Annotation Dictionary
    for anno in json_data['annotations']:
        if anno['iscrowd'] == 1:
            continue
        if category[label] == anno['category_id']:
            image_id = anno['image_id']
            if (image_id not in annodict):
                annodict[image_id] = []
                annodict[image_id].append(anno)
            else:
                annodict[image_id].append(anno)
    print(len(annodict.keys()), "images will be uploaded")
    for image in json_data['images']:
        file_name = image['file_name']
        width = image['width']
        height = image['height']
        image_id = image['id']
        if (image_id not in annodict):
            continue
        annolist = annodict[image_id]
        bbox = []
        for anno in annolist:
            x = ( float(anno['bbox'][0]) + ( float(anno['bbox'][2]) / 2) ) / width
            y = ( float(anno['bbox'][1]) + ( float(anno['bbox'][3]) / 2) ) / height
            w = float(anno['bbox'][2]) / width
            h = float(anno['bbox'][3]) / height
            bbox.append([x,y,w,h])
        payload = make_label(file_name, label, bbox)
        r = post.uploadImage(url, token, payload)
        if r:
            num += 1
            print("Upload Success ./upload_data/coco2017/train2017/%s" % file_name)
        else:
            print("Upload Fail.")

def upload_dataset(url, token, label):
    print("Coco Dataset 2017 Image Download")
    download_url = ["http://images.cocodataset.org/zips/train2017.zip"]
    tar_url = ["./upload_data/train2017.zip"]
    for down_url in download_url:
        if not os.path.isfile("./upload_data/train2017.zip"):
            wget.download(down_url, out="./upload_data/")
        else:
            print(down_url,"is already exist!")
    print("\n Downloaded OK. Unzip Dataset....")
    for tarURL in tar_url:
        zip_ref = zipfile.ZipFile(tarURL, 'r')
        zip_ref.extractall("./upload_data/coco2017/")
        zip_ref.close()
    print("extract OK.")
    print("Coco Dataset 2017 Annotation Download")
    if not os.path.isfile("./upload_data/annotations_trainval2017.zip"):
        wget.download("http://images.cocodataset.org/annotations/annotations_trainval2017.zip", out="./upload_data/")
    else:
        print("annotation already exist!")
    print("\n download OK. Unzip Annotation...")
    zip_ref = zipfile.ZipFile("./upload_data/annotations_trainval2017.zip", 'r')
    zip_ref.extractall("./upload_data/coco2017/")
    zip_ref.close()
    with open("./upload_data/coco2017/annotations/instances_train2017.json", 'r') as f:
        json_data = json.load(f)
        sendToIoTown(json_data, url, token, label)
    print("total",num,"file upload ok")


from core.utils import ViewDecorators
from django.shortcuts import render, redirect
from django.views.decorators.csrf import csrf_protect
from dashboard import forms, models

@csrf_protect
@ViewDecorators.require_user
def index(request):
    activity_type_list = models.ActivityType.get_user_activity_type_list(request.user['email'])

    if request.method == 'GET':
        form = forms.CreateActivityForm()
        form.prepare(activity_type_list)
    else:
        form = forms.CreateActivityForm(request.POST)
        form.prepare(activity_type_list)
        if form.is_valid():
            resp = models.Activity.create_activity(request.user['email'], form.cleaned_data)
    return render(request, 'index.html', locals())

@csrf_protect
@ViewDecorators.require_user
def create_activity_type(request):
    if request.method == 'GET':
        form = forms.AddActivityTypeForm()
    else:
        form = forms.AddActivityTypeForm(request.POST)
        if form.is_valid():
            resp = models.ActivityType.create_activity_type(request.user['email'], form.cleaned_data['name'])
            if resp['status'] == 'ActivityCreated':
                return redirect('dashboard')
    return render(request, 'create_type.html', locals())