import os
import random
import numpy as np

import torch
import torchvision.utils as tvu
import torchsde
from .Improved_Diffusion_Unconditional.improved_diffusion.sc09_spectrogram_dataset import melspec_inv_standardize, melspec_standardize

from .Improved_Diffusion_Unconditional.improved_diffusion.script_util import create_model_and_diffusion, model_and_diffusion_defaults
from .Improved_Diffusion_Unconditional.improved_diffusion.sc09_spectrogram_dataset import *

def _extract_into_tensor(arr_or_func, timesteps, broadcast_shape):
    """
    Extract values from a 1-D numpy array for a batch of indices.

    :param arr: the 1-D numpy array or a func.
    :param timesteps: a tensor of indices into the array to extract.
    :param broadcast_shape: a larger shape of K dimensions with the batch
                            dimension equal to the length of timesteps.
    :return: a tensor of shape [batch_size, 1, ...] where the shape has K dims.
    """
    if callable(arr_or_func):
        res = arr_or_func(timesteps).float()
    else:
        res = arr_or_func.to(device=timesteps.device)[timesteps].float()
    while len(res.shape) < len(broadcast_shape):
        res = res[..., None]
    return res.expand(broadcast_shape)

def restore_checkpoint(ckpt_dir, state, device):
    loaded_state = torch.load(ckpt_dir, map_location=device)
    state['optimizer'].load_state_dict(loaded_state['optimizer'])
    state['model'].load_state_dict(loaded_state['model'], strict=False)
    state['ema'].load_state_dict(loaded_state['ema'])
    state['step'] = loaded_state['step']

class RevVPSDE(torch.nn.Module):
    def __init__(self, model, score_type='guided_diffusion', beta_min=0.1, beta_max=20, N=1000,
                 img_shape=(1, 32, 32), model_kwargs=None):
        """Construct a Variance Preserving SDE.

        Args:
          model: diffusion model
          score_type: [guided_diffusion, score_sde, ddpm]
          beta_min: value of beta(0)
          beta_max: value of beta(1)
        """
        super().__init__()
        self.model = model
        self.score_type = score_type
        self.model_kwargs = model_kwargs
        self.img_shape = img_shape

        self.beta_0 = beta_min
        self.beta_1 = beta_max
        self.N = N
        self.discrete_betas = torch.linspace(beta_min / N, beta_max / N, N)
        self.alphas = 1. - self.discrete_betas
        self.alphas_cumprod = torch.cumprod(self.alphas, dim=0)
        self.sqrt_alphas_cumprod = torch.sqrt(self.alphas_cumprod)
        self.sqrt_1m_alphas_cumprod = torch.sqrt(1. - self.alphas_cumprod)

        self.alphas_cumprod_cont = lambda t: torch.exp(-0.5 * (beta_max - beta_min) * t**2 - beta_min * t)
        self.sqrt_1m_alphas_cumprod_neg_recip_cont = lambda t: -1. / torch.sqrt(1. - self.alphas_cumprod_cont(t))

        self.noise_type = "diagonal"
        self.sde_type = "ito"

    def _scale_timesteps(self, t):
        assert torch.all(t <= 1) and torch.all(t >= 0), f't has to be in [0, 1], but get {t} with shape {t.shape}'
        return (t.float() * self.N).long()

    def vpsde_fn(self, t, x):
        beta_t = self.beta_0 + t * (self.beta_1 - self.beta_0)
        drift = -0.5 * beta_t[:, None] * x
        diffusion = torch.sqrt(beta_t)
        return drift, diffusion

    def rvpsde_fn(self, t, x, return_type='drift'):
        """Create the drift and diffusion functions for the reverse SDE"""
        drift, diffusion = self.vpsde_fn(t, x)

        if return_type == 'drift':

            assert x.ndim == 2 and np.prod(self.img_shape) == x.shape[1], x.shape
            x_img = x.view(-1, *self.img_shape)

            if self.score_type == 'guided_diffusion':
                # model output is epsilon
                if self.model_kwargs is None:
                    self.model_kwargs = {}

                disc_steps = self._scale_timesteps(t)  # (batch_size, ), from float in [0,1] to int in [0, 1000]
                model_output = self.model(x_img, disc_steps, **self.model_kwargs)
                # with learned sigma, so model_output contains (mean, val)
                # model_output, _ = torch.split(model_output, self.img_shape[0], dim=1)
                assert x_img.shape == model_output.shape, f'{x_img.shape}, {model_output.shape}'
                model_output = model_output.view(x.shape[0], -1)
                score = _extract_into_tensor(self.sqrt_1m_alphas_cumprod_neg_recip_cont, t, x.shape) * model_output

            else:
                raise NotImplementedError(f'Unknown score type in RevVPSDE: {self.score_type}!')

            drift = drift - diffusion[:, None] ** 2 * score
            return drift

        else:
            return diffusion

    def f(self, t, x):
        """Create the drift function -f(x, 1-t) (by t' = 1 - t)
            sdeint only support a 2D tensor (batch_size, c*h*w)
        """
        t = t.expand(x.shape[0])  # (batch_size, )
        drift = self.rvpsde_fn(1 - t, x, return_type='drift')
        assert drift.shape == x.shape
        return -drift

    def g(self, t, x):
        """Create the diffusion function g(1-t) (by t' = 1 - t)
            sdeint only support a 2D tensor (batch_size, c*h*w)
        """
        t = t.expand(x.shape[0])  # (batch_size, )
        diffusion = self.rvpsde_fn(1 - t, x, return_type='diffusion')
        assert diffusion.shape == (x.shape[0], )
        return diffusion[:, None].expand(x.shape)

class RevImprovedDiffusion(torch.nn.Module):

    def __init__(self, args, config=None, device=None):
        super().__init__()
        self.args = args
        self.config = config
        if device is None:
            device = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
        self.device = device

        # load model
        img_shape = (1, 32, 32)
        model_dir = '_checkpoints'
        model_config = model_and_diffusion_defaults()
        # model_config.update(vars(self.config.model))
        # print(f'model_config: {model_config}')
        model, diffusion = create_model_and_diffusion(**model_config)
        model.load_state_dict(torch.load(args.ddpm_path, map_location='cpu'))

        # if model_config['use_fp16']:
        #     model.convert_to_fp16()

        model.eval().to(self.device)

        self.model = model
        self.diffusion = diffusion
        self.rev_vpsde = RevVPSDE(model=model, score_type=args.score_type, img_shape=img_shape,
                                  model_kwargs=None).to(self.device)
        self.betas = self.rev_vpsde.discrete_betas.float().to(self.device)

        print(f't: {args.t}, rand_t: {args.rand_t}, t_delta: {args.t_delta}')
        print(f'use_bm: {args.use_bm}')

    def image_editing_sample(self, img):

        assert isinstance(img, torch.Tensor)
        batch_size = img.shape[0]
        state_size = int(np.prod(img.shape[1:]))  # c*h*w

        assert img.ndim == 4, img.ndim
        img = img.to(self.device)

        x0 = melspec_standardize(img)
        xs = []
        for it in range(self.args.sample_step):

            e = torch.randn_like(x0).to(self.device)
            total_noise_levels = self.args.t
            if self.args.rand_t:
                total_noise_levels = self.args.t + np.random.randint(-self.args.t_delta, self.args.t_delta)
                print(f'total_noise_levels: {total_noise_levels}')
            a = (1 - self.betas).cumprod(dim=0).to(self.device)
            x = x0 * a[total_noise_levels - 1].sqrt() + e * (1.0 - a[total_noise_levels - 1]).sqrt()

            epsilon_dt0, epsilon_dt1 = 0, 1e-5
            t0, t1 = 1 - self.args.t * 1. / 1000 + epsilon_dt0, 1 - epsilon_dt1
            t_size = 2
            ts = torch.linspace(t0, t1, t_size).to(self.device)

            x_ = x.contiguous().view(batch_size, -1)  # (batch_size, state_size)
            if self.args.use_bm:
                bm = torchsde.BrownianInterval(t0=t0, t1=t1, size=(batch_size, state_size), device=self.device)
                xs_ = torchsde.sdeint_adjoint(self.rev_vpsde, x_, ts, method='euler', bm=bm)
            else:
                xs_ = torchsde.sdeint_adjoint(self.rev_vpsde, x_, ts, method='euler')

            x0 = xs_[-1].view(x.shape)  # (batch_size, c, h, w)
            x0 = melspec_inv_standardize(x0)

            # import librosa
            # import librosa.display
            # import matplotlib.pyplot as plt
            # from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
            # fig = plt.Figure()
            # canvas = FigureCanvas(fig)
            # ax = fig.add_subplot(111)
            # p = librosa.display.specshow(librosa.amplitude_to_db(x0[0].detach().cpu().numpy()), ax=ax, y_axis='log', x_axis='time')
            # fig.savefig('spec.png')

            xs.append(x0)

        return torch.cat(xs, dim=0)

    def forward(self, x):

        output = self.image_editing_sample(x)

        return output


# BSD 3-Clause License
#
# Copyright (c) 2017,
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * Redistributions in binary form must reproduce the above copyright notice,
#   this list of conditions and the following disclaimer in the documentation
#   and/or other materials provided with the distribution.
#
# * Neither the name of the copyright holder nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

# Copyright 2021 Huawei Technologies Co., Ltd
#
# Licensed under the BSD 3-Clause License  (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://opensource.org/licenses/BSD-3-Clause
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import argparse
import os
import sys
import torch
from collections import OrderedDict #定义有序字典
from conformer import Conformer
import onnx
import onnxruntime

def Conformer_tiny_patch16(pretrained=False, **kwargs):
    model = Conformer(patch_size=16, channel_ratio=1, embed_dim=384, depth=12,
                      num_heads=6, mlp_ratio=4, qkv_bias=True, **kwargs)
    if pretrained:
        raise NotImplementedError
    return model

def proc_nodes_module(checkpoint):
    new_state_dict = OrderedDict()
    for k, v in checkpoint.items():
        if "module." in k:
            name = k.replace("module.", "")
        else:
            name = k
        new_state_dict[name] = v
    return new_state_dict

def pth2onnx(input_file, output_file):
    model = Conformer_tiny_patch16()

    checkpoint = torch.load(input_file, map_location='cpu')
    checkpoint = proc_nodes_module(checkpoint)
    model.load_state_dict(checkpoint)

    # 调整模型为eval mode
    model.eval()
    # 输入节点名
    input_names = ["image"]
    # 输出节点名
    output_names = ["class"]
    dynamic_axes = {'image': {0: '-1'}, 'class': {0: '-1'}}
    dummy_input = torch.randn(1, 3, 224, 224) #修改输入shape
    # verbose=True，支持打印onnx节点和对应的PyTorch代码行
    torch.onnx.export(model, dummy_input, output_file, input_names = input_names,
                      dynamic_axes = dynamic_axes, output_names = output_names, opset_version=11, verbose=True)

if __name__ == '__main__':
    # model.load_state_dict({k.replace('module.',''):v for k,v in checkpoint['state_dict'].items()})
    try:
        # pth location
        xinput_file = sys.argv[1]
        # output onnx name
        xoutput_file = sys.argv[2]
    except IndexError:
        print("Stopped!")
        exit(1)

    if not (os.path.exists(xinput_file)):
        print("Please input pth location.")

    if not (os.path.exists(xoutput_file)):
        print("Please input onnx model name.")

    pth2onnx(xinput_file, xoutput_file)
    print("job success!")


import os
import sys
import time
import torch
import argparse
import numpy as np
from tqdm import tqdm

def cald(y, x, idx):
    '''calculate ay/a(x_idx)'''
    return torch.autograd.grad(y, x, grad_outputs=torch.ones_like(y), create_graph=True)[0][:,idx-1].reshape(-1, 1)

def autograd(y:torch.tensor, x:torch.tensor, order:int=10):
    '''calculate the n-order partial derivatives'''
    v = {0:[y]}
    p = x.numel()
    bar = order if p==1 else int((1-p**(order+1))/(1-p))-1
    pbar = tqdm(total=bar, desc='Calculating derivatives with Autograd', leave=True, file=sys.stdout)
    for k in range(1, order+1):
        v[k] = []
        for i in range(len(v[k-1])):    # eg. when p=3 and k=3, v[k-1] = [11, 12, 13, 21, 22, 23, ..., 33]
            for j in range(1, p+1):     # eg. when p=3 and k=3, v[k] = [111, 112, 113, 121, 122, 123, ..., 333]
                v[k].append(cald(v[k-1][i], x, j))
                pbar.set_postfix_str("order:{}, idx:{}/{}".format(k, i*p+j, len(v[k-1]*p)))
                pbar.update(1)
    return v

def main(net_path, order, point, show):
    net_dir = os.path.dirname(net_path)
    npy_dir = os.path.join(net_dir, 'npy')
    if not os.path.exists(npy_dir):
        os.mkdir(npy_dir)
    npy_path = os.path.join(npy_dir, f'Autograd_{point}_{order}').replace(" ","")

    # Forward propagation
    x = torch.tensor(point, dtype=torch.float, requires_grad=True)
    net = torch.load(net_path).eval()
    print(net)
    y = net(x)

    # Calculate all the derivatives
    time_start = time.time()
    v = autograd(y=y, x=x, order=order)
    time_auto = time.time()-time_start
    print('It takes {:.4f}s to calculate all the {}-order derivatives with Autograd.'.format(time_auto, order))
    v = {k: [float(d.detach().numpy()) for d in v[k]] for k in v.keys()}
    print(f'The number of derivatives of each order are: {str([len(v[k]) for k in v.keys()])}')
    np.save(npy_path, v)

    # Record the time cost
    time_dir = os.path.join(npy_dir, 'time')
    if not os.path.exists(time_dir):
        os.mkdir(time_dir)
    f = open(os.path.join(time_dir,f'Autograd_{point}_{order}.txt'), 'w+')
    f.write(f'Method: Autograd \nReference Point: {point} \nOrder: {order} \nTime Cost: {time_auto}s')
    f.close()

    # show results
    if show:
        for key in range(max(v.keys())+1):
            print(f'{key} order derivatives: {v[key]}')

if __name__=="__main__":
    parser = argparse.ArgumentParser(description='Taylor expansion')
    parser.add_argument('-d', type=str, default='outputs/test2d/net.pt', help='network path')
    parser.add_argument('-o', type=int, default=8, help='expansion order')
    parser.add_argument('-p', type=lambda s: [[float(item) if item[0]!='n' else -float(item[1:]) for item in s.split(',')]], default='0, 0', help='reference input')
    parser.add_argument('-s', action='store_true', help='show results')
    args = parser.parse_args()

    main(net_path=args.d, order=args.o, point=args.p, show=args.s)


from bs4 import BeautifulSoup
import requests

uname=input("Enter username:")
source=requests.get("https://myanimelist.net/profile/"+uname).text
soup=BeautifulSoup(source,'lxml')
#print(soup.prettify())

t1=soup.find('title').text
print(t1)

t2=soup.find('div',class_='stat-score di-t w100 pt8').text
print(t2)

print("Anime stats: ")
for t4 in soup.find_all('li',class_='clearfix mb12'):

   heading=t4.a.text+" "
   value=t4.span.text
   final=heading+value
   print(final)
   print(type(t4))

#----------------------------------------------ANIME SEARCH-------------------------------------------------------------------
@client.command()
async def ansearch(ctx):
   embed=discord.Embed(
      title='Which anime do you want to search?',
      description="Timeout in 10 seconds",
      colour=discord.Colour.green()

   )
   await ctx.send(embed=embed)
   def check(m):
      return m.author.id==ctx.author.id
   message=await client.wait_for('message',timeout=10,check=check)

   an=message.content
   search = AnimeSearch(an)

   for i in range(0,10):
      await ctx.send(str(i+1)+"."+search.results[i].title)

#----------------------------------------------MANGA SEARCH-------------------------------------------------------------------
@client.command()
async def masearch(ctx):
   embed=discord.Embed(
      title='Which manga do you want to search?',
      description="Timeout in 10 seconds",
      colour=discord.Colour.green()

   )
   await ctx.send(embed=embed)
   def check(m):
      return m.author.id==ctx.author.id
   message=await client.wait_for('message',timeout=10,check=check)

   ma=message.content
   search = MangaSearch(ma)

   for i in range(0,10):
      await ctx.send(str(i+1)+"."+search.results[i].title)


import numpy as np
import numpy.testing as npt
import pytest
from pycudadecon import affineGPU, deskewGPU, rotateGPU

def test_deskew(raw_image, deskewed_image):
    """test basic deskewing of a file aquired on a lattice light sheet"""
    deskewed = deskewGPU(raw_image, dzdata=0.3, angle=31.5, pad_val=98)
    npt.assert_allclose(deskewed, deskewed_image)

def test_affine_raises(raw_image):
    """Make sure that the affine transformation matrix must be the right size"""
    with pytest.raises(ValueError):
        affineGPU(raw_image, np.eye(5))
    with pytest.raises(ValueError):
        affineGPU(raw_image, np.eye(3))
    with pytest.raises(ValueError):
        affineGPU(raw_image, np.eye(2))

def test_affine_eye(raw_image):
    """test that an affine transform with identity matrix does not change the input"""
    result = affineGPU(raw_image, np.eye(4))
    npt.assert_allclose(result, raw_image)

def test_affine_translate(raw_image):
    """
    test affine translation leads to a bunch of empty values up to
    but not more than the requested amount of translation
    """
    xpix = -50
    ypix = -100
    zpix = -3
    T = np.array([[1, 0, 0, xpix], [0, 1, 0, ypix], [0, 0, 1, zpix], [0, 0, 0, 1]])
    result = affineGPU(raw_image, T)
    assert not np.allclose(raw_image, result, atol=10)
    assert np.all(result[:-zpix] == 0)
    assert not np.all(result[: -zpix + 1] == 0)
    assert np.all(result[:, :-xpix, :-zpix] == 0)

def test_affine_translate_RA(raw_image):
    """
    make sure the referenceing object works to accept transformation
    matrices in units of sample space, instead of world coordinates
    """
    xpix = -50
    ypix = -100
    zpix = -3
    T = np.array([[1, 0, 0, xpix], [0, 1, 0, ypix], [0, 0, 1, zpix], [0, 0, 0, 1]])
    voxsize = (0.5, 0.5, 0.5)
    result = affineGPU(raw_image, T, voxsize)
    assert not np.allclose(raw_image, result, atol=10)
    assert np.all(result[: -zpix * 2] == 0)
    assert not np.all(result[: (-zpix * 2) + 1] == 0)
    assert np.all(result[:, : -xpix * 2, : -zpix * 2] == 0)

def test_rotate(deskewed_image, rotated_image):
    """test that rotateGPU rotates the image on the Y axis by some angle"""
    result = rotateGPU(deskewed_image, 0.3, dxdata=0.1, angle=31.5)
    npt.assert_allclose(result, rotated_image)


from connect import cursor as c
import utils

db = utils.read("DB: ")
table = utils.read("Table: ")

try:
    sql = """INSERT INTO {}.dbo.{}
    VALUES(100001,'John Rambo',100,'HD')""".format(db,table)
    c.execute(sql)
    print(f'A new record has been created!!!')
except ConnectionError:
    print("Cannot connect to SQL Server")


from django.shortcuts import render
from django.http import HttpResponse, HttpResponseBadRequest, HttpResponseForbidden
from django.views.decorators.csrf import csrf_exempt
from django.conf import settings

from linebot import LineBotApi, WebhookParser
from linebot.exceptions import InvalidSignatureError, LineBotApiError
from linebot.models import (
    MessageEvent,
    TextSendMessage,
    FlexSendMessage,
    ImageSendMessage,
    TemplateSendMessage,
    ButtonComponent,
    TextComponent,
    SeparatorComponent,
    BubbleContainer,
    BoxComponent,
    MessageAction)

import re
import numpy as np
import matplotlib.pyplot as plt

#function
from .dynamic_list_generator import favorite_list_generator #最愛清單function
from .datedo import datedo_list_generator  #對象工具列
from .carousel import carousel_list
from .report import draw,text_report
from .TextTemplate import instrution_content
from .connector import selectChattingObjectNameByUserLineId,addUser,addChattingObject,addRecord
from .partition import frequency,wordanalysis
#from .test import getAmountScore,getSpeedScore

#登入linebot 跟 imgur 需要的東西(from settings)
line_bot_api = LineBotApi(settings.LINE_CHANNEL_ACCESS_TOKEN)
parser = WebhookParser(settings.LINE_CHANNEL_SECRET)
imgur_client=settings.IMGUR_CLIENT_ID

######需要從後端得到的東西######
favorite_list=[] #最愛清單(from db)

values = [60,51,70,80,60,50] #各指標本次分數(from model)
values_a= [40,50,80,70,90,60] #各指標平均分數(from DB)

#本次分數
get_point_a=80.5
#上次分數
get_point_b=77.5

#把分數型態轉變為字串
point=str(get_point_a)
difference=str(get_point_a-get_point_b)

#話題主題前三名
topic=["Travel","Sports","Fashion"]

#主題1新聞連結
topic1=["https://www.youtube.com/channel/UC0C-w0YjGpqDXGB8IHb662A",
        "https://www.youtube.com/channel/UC0C-w0YjGpqDXGB8IHb662A",
        "https://www.youtube.com/channel/UC0C-w0YjGpqDXGB8IHb662A"]
#主題2新聞連結
topic2=["https://www.youtube.com/channel/UC0C-w0YjGpqDXGB8IHb662A",
        "https://www.youtube.com/channel/UC0C-w0YjGpqDXGB8IHb662A",
        "https://www.youtube.com/channel/UC0C-w0YjGpqDXGB8IHb662A"]
#主題3新聞連結
topic3=["https://www.youtube.com/channel/UC0C-w0YjGpqDXGB8IHb662A",
        "https://www.youtube.com/channel/UC0C-w0YjGpqDXGB8IHb662A",
        "https://www.youtube.com/channel/UC0C-w0YjGpqDXGB8IHb662A"]

@csrf_exempt
def callback(request):
    if request.method == 'POST':
        signature = request.META['HTTP_X_LINE_SIGNATURE']
        body = request.body.decode('utf-8')

        try:
            events = parser.parse(body, signature)  # 傳入的事件
            print(events)

        except InvalidSignatureError:
            return HttpResponseForbidden()
        except LineBotApiError:
            return HttpResponseBadRequest()

        global topic
        global favorite_list
        for event in events:

            if isinstance(event, MessageEvent):

                if event.message.type=='file': #############分析完後要回傳到資料庫##################
                    fname1=event.message.file_name[8:]
                    fname2=fname1[:-7]
                    user_id=event.source.user_id
                    file_path = f'/tmp/{user_id}:{fname2}'
                    message_content = line_bot_api.get_message_content(event.message.id)
                    with open(file_path, 'wb') as fd:
                        for chunk in message_content.iter_content():
                            fd.write(chunk)

                    addRecord(user_id,fname2)
                    line_bot_api.reply_message(event.reply_token, TextSendMessage(text="成功傳送對話："+fname2))

                elif re.match('頻率：', event.message.text):
                    file_path = f'/tmp/{event.source.user_id}:{event.message.text[3:]}'
                    b=frequency(file_path)
                    line_bot_api.reply_message(event.reply_token, TextSendMessage(text=b))

                elif re.match('情感：', event.message.text):
                    file_path = f'/tmp/{event.source.user_id}:{event.message.text[3:]}'
                    c=wordanalysis(file_path)
                    line_bot_api.reply_message(event.reply_token, TextSendMessage(text=c))

                elif event.message.text == '報表說明':
                    line_bot_api.reply_message(event.reply_token, TextSendMessage(text = instrution_content()))

#####第一次使用需要註冊帳號######
                elif event.message.text == '我要註冊':
                    user_id = event.source.user_id
                    addUser(user_id)
                    line_bot_api.reply_message(event.reply_token, TextSendMessage(text="註冊成功！"))

#####查看分析名單######
                elif event.message.text == '分析名單':
                    user_id = event.source.user_id
                    tup=selectChattingObjectNameByUserLineId(user_id)
                    favorite_list=[]
                    for i in range(len(tup)):
                        favorite_list.append(tup[i][0])
                    favorite_list_button=favorite_list_generator(favorite_list)
                    flex_message1=FlexSendMessage(alt_text='分析名單',contents=favorite_list_button)
                    line_bot_api.reply_message(event.reply_token, flex_message1)

                elif re.match("搜尋對象:", event.message.text):
                    date=event.message.text[5:] # 對象名稱(date)
                    flex_message2=FlexSendMessage(alt_text=date,contents=datedo_list_generator(date))
                    line_bot_api.reply_message(event.reply_token, flex_message2)

#####新增對象######
                elif re.match("新增對象：", event.message.text):
                    name=event.message.text[5:]
                    user_id = event.source.user_id
                    addChattingObject(name,user_id)
                    favorite_list.append(name)
                    line_bot_api.reply_message(event.reply_token, TextSendMessage(text="成功新增對象:"+event.message.text[5:]))

#####刪除對象#####還沒完成
                elif re.match("刪除對象:", event.message.text):
                    favorite_list.remove(event.message.text[5:])
                    line_bot_api.reply_message(event.reply_token, TextSendMessage(text="成功刪除對象:"+event.message.text[5:]))

                elif re.match("尋找話題:", event.message.text):
                    flex_message3=carousel_list(topic,topic1,topic2,topic3)
                    line_bot_api.reply_message(event.reply_token, flex_message3)

######從資料庫抓1.最新分數＆次新分數陣列 2.最新指標＆次新指標陣列 3.平均指標######還沒完成
                elif re.match("目前好感度:", event.message.text):
                    reply_arr=[]
                    t_content=text_report(values,values_a)
                    txt=TextSendMessage(text=t_content)
                    reply_arr.append(txt)
                    i_content = draw(imgur_client,values,values_a,point,difference)
                    img=ImageSendMessage(original_content_url=i_content,preview_image_url=i_content)
                    reply_arr.append(img)
                    line_bot_api.reply_message(event.reply_token, reply_arr)

                elif re.match("開始新增對象，請輸入「新增對象：對象名稱」", event.message.text):
                   pass

                elif re.match("請開始上傳對話", event.message.text):
                    pass
                else:
                    line_bot_api.reply_message(event.reply_token,TextSendMessage(text="請輸入有效指令"))

        return HttpResponse()
    else:
        return HttpResponseBadRequest()


#!/usr/bin/env python
# coding: utf-8

# Trader Joe's web site is designed in a way that information of a store can be find by
#first determining the state where the store is located. Thus, [list of states in which
#Trader Joe's located](https://locations.traderjoes.com/) is welcomed us. Then, one needs
#to determine [the city](https://locations.traderjoes.com/ca/) within a specific state
#where the store is located so that one can see [the list of all the stores](https://locations.traderjoes.com/ca/los-angeles/)
#within the selected city.

# In general it can be summarized as: State(e.g. Califronia)-> City(e.g. Los Angles)-> Store(e.g. Trader Joe's Hollywood). Hence, I planned my scraping strategy accordingly: define 3 main specific functions that makes the transition between each parts possible. Luckly, their site has static content which can be easily scraped by utilizing [the Beautiful Soup module.](https://www.crummy.com/software/BeautifulSoup/bs4/doc/).

#libraries that you would need
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import requests #makes the http request, necessary for geocoding
from bs4 import BeautifulSoup #module for static web site scraping
import json #reads and downloads json formats from the website
from geopy.geocoders import Nominatim #geocoding
from geopy.exc import GeocoderTimedOut
from geopy.extra.rate_limiter import RateLimiter
import re #string manipulation
import time #sleep Zzzz.
import folium #mapping
import geopandas #geospatial data
import pickle #to pickle (ssaving with very low sizes)
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.preprocessing import StandardScaler

#parses all the state links in the first page where list of all the states with Trader Joe's are listed.
def parse_statelinks(states):

    URL_state = states.find('a')['href']
    page_state = requests.get(URL_state)

    soup_state = BeautifulSoup(page_state.content, "html.parser")
    results_state = soup_state.find(id="contentbegin")
    cities = results_state.find_all("div", class_="itemlist")

    return cities

#Makes the transition from the selected state, and parses (returns) the cities with Trader Joe's within
def states2cities(soup):
    cities = []
    results = soup.find(id="contentbegin")
    states = results.find_all("div", class_="itemlist")
    cities.extend([parse_statelinks(states[i]) for i in range(len(states))])

    return cities

#Makes the transition from the selected city, and parses the stores (Trader Joe's) within,
#returns list of dictionaries (json format) that contains address information about each store.

def city2stores(city):
    store_list = []

    URL_city = city.find('a')['href']
    page_city = requests.get(URL_city)
    soup_city = BeautifulSoup(page_city.text, "html.parser")

    results_city = soup_city.find(id="contentbegin")
    city_results = results_city.find_all("script", {"type":"application/ld+json"})

    for i in range(len(city_results)):
        store_list.append(json.loads("".join(results_city.find_all("script", {"type":"application/ld+json"})[i])))

    return store_list

#Geocode the given store addresses from address string to shapely point object.

def city_geocode(store):

    PostalAddress = store['address']

    #create the full adress of the store whom you want to geocode, fix the abbrivation (e.g. change Rd. to Road)
    street_address = street_address_fix(PostalAddress['streetAddress'])
    address = street_address.split(',')[0] + ', ' + PostalAddress['addressLocality'] + ', ' + PostalAddress['addressRegion'] + ', '+ PostalAddress['addressCountry']

    #geocode using OSM Nominatim
    rnd = np.random.randint(1, 20)
    time.sleep(rnd)

    #first try to geocode the given address as it is written
    location = locator.geocode(address)

    #if doesn't work tweak the given address: remove any numbers,except the postal code, in the main part of the given address
    if location is None:
        street_address = re.sub(r'[0-9]+', '', street_address.split(',')[0])
        address = street_address + ', ' + PostalAddress['addressLocality'] + ', ' + PostalAddress['addressRegion'] + ', '+ PostalAddress['addressCountry']
        location = locator.geocode(address)

    #if doesn't work tweak the given address: get rid of address related verbs as Road, Street etc. additionally
    if location is None:
        street_address = street_abbv_remove(street_address)
        address = street_address + ', ' + PostalAddress['addressLocality'] + ', ' + PostalAddress['addressRegion'] + ', '+ PostalAddress['addressCountry']
        location = locator.geocode(address)

    #if it doesnt work just take the center of the city as the last resort.
    if location is None:
        address = PostalAddress['addressLocality'] + ', ' + PostalAddress['addressRegion'] + ', '+ PostalAddress['addressCountry'] + ', ' + PostalAddress['postalCode']
        location = locator.geocode(address)

    try:
        return [dict({'address': location.address, 'lon': location.longitude, 'lat' : location.latitude , 'point' : location.point})]
    except:
        return dict({})

#function that helps to make street related abbrivation changes.
def street_address_fix(StreetAddress):
    replacements = {'RD': 'ROAD',
                    'RD.': 'ROAD',
                    'CIR': 'CIRCLE',
                    'CIR.': 'CIRCLE',
                    'DR': 'DRIVE',
                    'DR.': 'DRIVE',
                    'LN': 'LANE',
                    'LN.': 'LANE',
                    'CT': 'COURT',
                    'CT.': 'COURT',
                    'PL': 'PLACE',
                    'PL.': 'PLACE',
                    'ST': 'STREET',
                    'ST.': 'STREET',
                    'BLVD': 'BOULEVARD',
                    'BLVD.': 'BOULEVARD'}

    StreetAddress = StreetAddress.upper().split()

    for i in range(len(StreetAddress)):
        if StreetAddress[i] in replacements.keys():
            StreetAddress[i] = replacements[StreetAddress[i]]

    StreetAddress = ' '.join(StreetAddress)
    StreetAddress = ' '.join( [s for s in StreetAddress.split() if len(s)>2] )

    return StreetAddress

def street_abbv_remove(StreetAddress):
    replacements = {'ROAD': ' ',
                    'CIRCLE': ' ',
                    'DRIVE': ' ',
                    'LANE': ' ',
                    'COURT': ' ',
                    'PLACE': ' ',
                    'STREET': ' ',
                    'BOULEVARD': ' '}

    StreetAddress = StreetAddress.upper().split()

    for i in range(len(StreetAddress)):
        if StreetAddress[i] in replacements.keys():
            StreetAddress[i] = replacements[StreetAddress[i]]

    StreetAddress = ' '.join(StreetAddress)
    StreetAddress = ' '.join( [s for s in StreetAddress.split() if len(s)>2] )

    return StreetAddress

#The main part, for loop and the functions within returns a list of dictionaries, one needs to convert them
#into dataframe in order to get something like the one that I shared in the dataset section.

URL = "https://locations.traderjoes.com/"

page = requests.get(URL)
soup = BeautifulSoup(page.content, "html.parser")
geopy.geocoders.options.default_timeout = 25 #set high to not get Max retries exceeded type of error
locator = Nominatim(user_agent="personal_project")

stores = []
states = states2cities(soup) #lists of all the states url where store related informations exist

for j in range(len(states)): #state -> city
    for i in range(len(states[j])):   #city -> store
        tmp = city2stores(states[j][i])
        for k in range(len(tmp)):  # ..stores..
            a = city_geocode(tmp[k])
            stores.extend(a)

#with open('stores.pickle', 'wb') as handle:
#pickle.dump(stores, handle, protocol=pickle.HIGHEST_PROTOCOL)

#Small fix with one address

stores_data = pd.DataFrame(stores)

address = stores_data[stores_data.lon==stores_data.lon.max()].address
locator = Nominatim(user_agent="personal_project")

stores[384]['address'] = locator.geocode('77 Boston Turnpike, Shrewsbury, MA,USA').address
stores[384]['lon'] =locator.geocode('77 Boston Turnpike, Shrewsbury, MA,USA').longitude
stores[384]['lat'] = locator.geocode('77 Boston Turnpike, Shrewsbury, MA,USA').latitude
stores[384]['point'] = locator.geocode('77 Boston Turnpike, Shrewsbury, MA,USA').point

#Ground Truths of Warehouse addresses
warehouse_address = ['Nazareth, PA 18064, USA', 'Suwanee, GA 30024, USA', '30 Commerce Blvd, Middleborough, MA , USA',
                    'Minooka 60447, IL, USA','5111 Bear Creek Ct, Irving, TX 75061, USA','2388 Mason Ave, Daytona Beach, FL 32117, USA',
                    '200 Phoenix Xing, Bloomfield, CT 06002, USA','10288 Calabash Ave, Fontana, CA 92335, USA','2121 Boeing Way, Stockton, CA 95206, USA',
                    '3707 Hogum Bay Rd NE, Lacey, WA 9851','4681 Edison Ave, Chino, CA 91710, USA','10401 W Van Buren St, Tolleson, AZ 85353, USA']

def real_warehouse_address(rwa):

    adrs = locator.geocode(rwa)
    return [dict({'address': adrs.address, 'lon': adrs.longitude, 'lat' : adrs.latitude , 'point' : adrs.point})]

rwa = []
for adrs in warehouse_address:
    rwa.append(real_warehouse_address(adrs))

### Analysis Part

coordinates = stores_data[['lon','lat']].values
#standardize? or Not
#scaler = StandardScaler()
#scaled_coordinates = scaler.fit_transform(coordinates)

kmeans = KMeans(
    init="k-means++",
    n_clusters=19,
    n_init=10,
    max_iter=100, random_state=17)
kmeans.fit(coordinates)

warehouse = pd.DataFrame(kmeans.cluster_centers_, columns = ['lon','lat'])
labels = pd.DataFrame(kmeans.labels_, columns= ['labels'])
stores_data = pd.concat([stores_data,labels], axis = 1 )
stores_data['labels'] = stores_data['labels'].astype(str)

#Mapping with folium part
m = folium.Map(location=[37, -102], zoom_start=4)

stores_data.apply(lambda row:folium.CircleMarker(location=[row["lat"], row["lon"]],
                                              radius=1.5, color='orange')
                                             .add_to(m), axis=1)

for w in range(len(warehouse)):

    folium.CircleMarker(
        location=[warehouse.iloc[w]['lat'],warehouse.iloc[w]['lon']],
        radius=5,
        popup="Laurelhurst Park",
        color="darkred",
        fill=True,
        fill_color="darkred",
    ).add_to(m)

for j in stores_data.labels.unique():
    temp = stores_data[stores_data.labels==j]
    for i in range(len(temp)):
        folium.PolyLine([(warehouse.loc[int(j)].lat,warehouse.loc[int(j)].lon),(temp.iloc[i].lat,temp.iloc[i].lon)],
                        color='black',
                        weight=1,
                        opacity=0.6).add_to(m)

for k in range(len(rwa)):

    folium.CircleMarker(
        location=[rwa[k][0]['lat'],rwa[k][0]['lon']],
        radius=5,
        color="green",
        fill=True,
        fill_color="green",
        opacity = 1
    ).add_to(m)

m

# In[ ]:
#stores_data.groupby(['labels']).address.count()


import math
import logging
from functools import partial
from collections import OrderedDict

import torch
import torch.nn as nn
import torch.nn.functional as F
from timm.data import IMAGENET_DEFAULT_MEAN, IMAGENET_DEFAULT_STD
# from .layers import StdConv2dSame, DropPath, to_2tuple, trunc_normal_
from timm.models.layers import DropPath, to_2tuple, trunc_normal_
from timm.models.vision_transformer import DropPath, Mlp
from transformers.models.bert.modeling_bert import BertSelfAttention
_logger = logging.getLogger(__name__)

class Mlp(nn.Module):
    def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.):
        super().__init__()
        out_features = out_features or in_features
        hidden_features = hidden_features or in_features
        self.fc1 = nn.Linear(in_features, hidden_features)
        self.act = act_layer()
        self.fc2 = nn.Linear(hidden_features, out_features)
        self.drop = nn.Dropout(drop)

    def forward(self, x):
        x = self.fc1(x)
        x = self.act(x)
        x = self.drop(x)
        x = self.fc2(x)
        x = self.drop(x)
        return x

class Attention(nn.Module):
    def __init__(self, dim, num_heads=8, qkv_bias=False, qk_scale=None, attn_drop=0., proj_drop=0.):
        super().__init__()
        self.num_heads = num_heads
        head_dim = dim // num_heads
        # NOTE scale factor was wrong in my original version, can set manually to be compat with prev weights
        self.scale = qk_scale or head_dim ** -0.5

        self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
        self.attn_drop = nn.Dropout(attn_drop)
        self.proj = nn.Linear(dim, dim)
        self.proj_drop = nn.Dropout(proj_drop)

    def forward(self, x, attention_mask=None):
        B, N, C = x.shape
        qkv = self.qkv(x).reshape(B, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
        q, k, v = qkv[0], qkv[1], qkv[2]   # make torchscript happy (cannot use tensor as tuple)

        attn = (q @ k.transpose(-2, -1)) * self.scale
        if attention_mask is not None:
            attn = attn + attention_mask
        attn = attn.softmax(dim=-1)
        attn = self.attn_drop(attn)

        x = (attn @ v).transpose(1, 2).reshape(B, N, C)
        x = self.proj(x)
        x = self.proj_drop(x)
        return x

class Block(nn.Module):

    def __init__(self, dim, num_heads, mlp_ratio=4., qkv_bias=False, qk_scale=None, drop=0., attn_drop=0.,
                 drop_path=0., act_layer=nn.GELU, norm_layer=nn.LayerNorm):
        super().__init__()
        self.norm1 = norm_layer(dim)
        self.attn = Attention(
            dim, num_heads=num_heads, qkv_bias=qkv_bias, qk_scale=qk_scale, attn_drop=attn_drop, proj_drop=drop)
        # NOTE: drop path for stochastic depth, we shall see if this is better than dropout here
        self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()
        self.norm2 = norm_layer(dim)
        mlp_hidden_dim = int(dim * mlp_ratio)
        self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)

    def get_extended_attention_mask(self, attention_mask, input_shape):
        if attention_mask.dim() == 3:
            extended_attention_mask = attention_mask[:, None, :, :]
        elif attention_mask.dim() == 2:

            extended_attention_mask = attention_mask[:, None, None, :]
        else:
            raise ValueError(
                f"Wrong shape for input_ids (shape {input_shape}) or attention_mask (shape {attention_mask.shape})"
            )
        extended_attention_mask = extended_attention_mask  # fp16 compatibility
        extended_attention_mask = (1.0 - extended_attention_mask) * -10000.0
        return extended_attention_mask

    def forward(self, x, attn_mask=None):
        if attn_mask is not None:
            attn_mask = self.get_extended_attention_mask(attn_mask, x.shape)
        x = x + self.drop_path(self.attn(self.norm1(x), attn_mask))
        x = x + self.drop_path(self.mlp(self.norm2(x)))
        return x

class BertAttention(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.self = BertSelfAttention(config)
        self.dense = nn.Linear(config.hidden_size, config.hidden_size)
        self.dropout = nn.Dropout(config.hidden_dropout_prob)

    def forward(
        self,
        hidden_states,
        attention_mask=None,
        encoder_hidden_states=None,
        encoder_attention_mask=None,
    ):
        self_outputs = self.self(
            hidden_states=hidden_states,
            attention_mask=attention_mask,
            encoder_hidden_states=encoder_hidden_states,
            encoder_attention_mask=encoder_attention_mask,
        )
        attention_output = self.dense(self_outputs[0])
        attention_output = self.dropout(attention_output) + hidden_states

        return attention_output

class TransformerCrossAttnLayer(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.norm1 = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
        self.attention = BertAttention(config)

        self.cross_norm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
        self.crossattention = BertAttention(config)

        self.norm2 = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
        self.mlp = Mlp(in_features=config.hidden_size, hidden_features=config.hidden_size*4, out_features=config.hidden_size)

    def get_extended_attention_mask(self, attention_mask):
        if attention_mask.dim() == 3:
            extended_attention_mask = attention_mask[:, None, :, :]
        elif attention_mask.dim() == 2:
            extended_attention_mask = attention_mask[:, None, None, :]
        else:
            raise ValueError
        extended_attention_mask = extended_attention_mask  # fp16 compatibility
        extended_attention_mask = (1.0 - extended_attention_mask) * -10000.0
        return extended_attention_mask

    def forward(
        self,
        hidden_states,
        attention_mask=None,
        encoder_hidden_states=None,
        encoder_attention_mask=None,
    ):
        attention_mask = self.get_extended_attention_mask(attention_mask) if attention_mask is not None else None
        encoder_attention_mask = self.get_extended_attention_mask(encoder_attention_mask) if encoder_attention_mask is not None else None

        hidden_states = self.norm1(hidden_states)
        attention_output = self.attention(hidden_states, attention_mask)

        attention_output = self.cross_norm(attention_output)
        attention_output = self.crossattention(
            attention_output,
            attention_mask,
            encoder_hidden_states,
            encoder_attention_mask,
        )

        attention_output = self.norm2(attention_output)
        layer_output = self.mlp(attention_output)
        layer_output += attention_output

        return layer_output


class TheisWell:
    """Theis (1935) radial flow solution.

    The default TheisWell object uses the default Aq2dConf and WellGrid
    classes. The WellGrid class includes the default Well class. Methods
    include radius of influence .ri, transient drawdown at a point .dd and
    grid-contoured drawdown at specified time .dd_grid.

    Attributes:
        aq (obj) : Aq2dConf aquifer object.
        grd (obj) : WellGrid object.
        qf (float) : Fraction of pumped volume used for calculating radius of
            influence (default 0.99).

    """
    from pygaf.aquifers import Aq2dConf
    from pygaf.grids import WellGrid
    def __init__(self):
        self.aq = self.Aq2dConf()
        self.grid = self.WellGrid()
        self.well = self.grid.well
        self.qf = 0.99
        return

    @property
    def qfp(self):
        """float : Fraction of pumped volume."""
        return self.qf

    def info(self):
        """Print the solution information."""
        print('METHOD REFERENCE')
        print('----------------')
        print(
        'Theis C. V. (1935) - The relation between the lowering of the' +
        '\npiezometric surface and the rate and duration of discharge of a' +
        '\nwell using ground-water storage.'
        )
        print('\nConceptual Model:')
        print('- Infinite, confined, uniform and homogeneous aquifer.')
        print('- Radial groundwater flow.')
        print('- Steady state and fully penetrating well.')
        print('- No groundwater recharge.')
        print()

    def rinf(self, T, S, t, qf):
        """Radius of influence."""
        from numpy import sqrt, log
        return sqrt(-4.0 * T * t * log(1-qf) / S)

    def disp(self, r, S, T, t, Q):
        """Drawdown displacement."""
        from numpy import pi
        from scipy.special import expn
        u = (r**2) * S / (4.0 * T * t)
        W = expn(1, u) # Well Function
        return Q * W / (4.0 * pi * T)

    def ri(self, t=[1.0], q=-1000, plot=True, csv='', xlsx=''):
        """Calculate radius of influence at specified times.

        Radius of influence is defined as the radius from within which a
        specified faction qf of the pumped volume has been drawn. The default
        value for qf is 0.99, corresponding to the radius from which 99% of the
        pumped volume has been drawn.

        Time for calculating ri are provided in a list. A results graph is
        displayed as default and can be suppressed by setting plot=False. A
        pandas dataframe is returned with time as the row index and ri as
        a column.

        Results can be exported to csv and Excel files by setting non-blank
        filename strings for the .csv and .xlsx attributes. Filenames can be
        supplied with or without file extentions, which are added if ommitted.

        Args:
            t (float) : List of times to evaluate radius of influence
                (default [1.0]).
            plot (bool) : Display a plot of results (default True).
            csv (str) : Full filepath for export of results to csv file;
                results are exported if the string is not empty (default '').
            xlsx (str) : Full filepath for export of result to xlsx file;
                results are exported if the string is not empty (default '').

        Returns:
            Results in pandas dataframe.

        """
        import pandas
        self.well.q = q
        # Checks
        if self.qfp < 0 or self.qfp > 1:
            print('Error! The value of qf must be between 0 and 1.')
            return
        if min(t) <= 0:
            print('Error! All times must be greater than 0.')
            return
        # Radius of influence
        ri = []
        for tim in t:
            ri.append(self.rinf(self.aq.T, self.aq.S, tim, self.qfp))
        d = {'Time':t, 'ri':ri}
        df = pandas.DataFrame(data=d)
        df.set_index('Time', inplace=True)
        # Results plot
        if plot:
            import matplotlib.pyplot as plt
            df.plot(grid=True, marker='.', lw=3, alpha=0.5, ylabel='Radius')
            plt.xlim(0, None)
            plt.ylim(0, None)
            plt.title('Radius of Influence\n' +
                'T = ' + str(self.aq.T) +
                ', S = ' + str(self.aq.S) +
                ', q =' + str(self.well.q) +
                ', qf = ' + str(self.qfp)
                )
            plt.show()
        # Export result to csv
        if csv != '':
            if csv.split('.') != 'csv':
                csv = csv + '.csv'
            df.to_csv(csv)
            print('Results exported to:', csv)
        # Export result to Excel
        if xlsx != '':
            if xlsx.split('.') != 'xlsx':
                xlsx = xlsx + '.xlsx'
            df.to_excel(xlsx, sheet_name='ri')
            print('Results exported to:', xlsx)
        return df

    def dd(self, t=[1], r=[1], q=-1000.0, plot=True, csv='', xlsx=''):
        """Evaluate drawdown at specified radii and times.

        Evaluate drawdown at each radius and time specified in the lists t
        and r and for well rate q. Defaults are t=[1.0], r=[1.0] and
        q=-1000.0. A drawdown graph is displayed as default and can be
        suppressed by setting plot=False.

        A pandas dataframe of drawdown values is returned with time as the row
        index and radius values as the column headers. Results can be exported
        to csv and Excel files by setting non-blank filename strings for the
        .csv and .xlsx attributes. Filenames can be supplied with or without
        file extentions, which are added if ommitted.

        Args:
            t (float) : List of times to evaluate drawdown (default [1.0]).
            r (float) : List of radii to evaluate drawdown (default [1.0]).
            plot (bool) : Display a plot of results (default True).
            csv (str) : Full filepath for export of results to csv file;
                results are exported if the string is not empty (default '').
            xlsx (str) : Full filepath for export of result to xlsx file;
                results are exported if the string is not empty (default '').

        Returns:
            Results in a pandas dataframe.

        """
        import pandas
        self.well.q = q
        # Checks
        if min(t) <= 0 or min(r) <= 0:
            print('Error! All times and radii must be greater than 0.')
            return
        # Calculate drawdown
        d = {'Time':t}
        df = pandas.DataFrame(data=d)
        df.set_index('Time', inplace=True)
        for rad in r:
            drawdown = []
            for tim in t:
                dd = self.disp(rad, self.aq.S, self.aq.T, tim, self.well.q)
                drawdown.append(dd)
            df['r' + str(rad)] = drawdown
        # Plot results
        if plot:
            import matplotlib.pyplot as plt
            df.plot(
                grid=True, marker='.', lw=3, alpha=0.5, ylabel='Displacement'
                )
            plt.title('Drawdown\n' +
                'T = ' + str(self.aq.T) +
                ', S = ' + str(self.aq.S) +
                ', q = ' + str(self.well.q)
                )
            plt.legend(
                r, ncol=5, mode='expand', loc='upper left',
                bbox_to_anchor=(0,-0.1, 1, -0.1)
            )
            plt.show()
        # Export results
        if csv != '':
            if csv.split('.') != 'csv':
                csv = csv + '.csv'
            df.to_csv(csv)
            print('Results exported to:', csv)
        if xlsx != '':
            if xlsx.split('.') != 'xlsx':
                xlsx = xlsx + '.xlsx'
            df.to_excel(xlsx, sheet_name='ri')
            print('Results exported to:', xlsx)
        return df

    def dd_grid(self, t=1.0, q=-1000.0, plot=True, local=False, csv='',
    xlsx=''):
        """Evaluate drawdown on a regular grid.

        Evaluate drawdown on a grid of points at specified time and well rate.
        Default values are t=1.0 and q=-1000. Unless otherwise specified, a
        default WellGrid object is used; it can be accessed and adjusted via
        the .grid.gr (grid radius) and .grid.gd (grid density) attributes.

        Results are returned in a Pandas dataframe with column x-coord, y-coord
        and drawdown value. A drawdown graph is displayed as default and can
        be suppressed by setting plot=False.

        Args:
            t (float) : Time of drawdown (default 1.0).
            plot (bool) : Display a plot of results (default True).
            local (bool) : Display the results in 'local' coordinates with the
                well at coordinates 0.0, 0.0 (Default False).
            csv (str) : Full filepath for export of results to csv file;
                results are exported if the string is not empty (default '').
            xlsx (str) : Full filepath for export of result to xlsx file;
                results are exported if the string is not empty (default '').

        Returns:
            Results in a pandas dataframe.

        """
        import matplotlib.pyplot as plt
        import pandas
        self.well.q = q
        # Set coordinates
        if local:
            x, y = list(self.grid.pts.locx), list(self.grid.pts.locy)
            wx, wy = 0, 0
            plot_title = 'Drawdown at radius < ' + str(self.grid.gr) +\
            ' and t = ' + str(t) + '\n(local coordinates)'
        else:
            x, y = list(self.grid.pts.worldx), list(self.grid.pts.worldy)
            wx, wy = self.grid.well.x, self.grid.well.y
            plot_title = 'Drawdown at radius < ' + str(self.grid.gr) +\
            ' and t = ' + str(t) + '\n(world coordinates)'
        # Calculate drawdown
        radius, drawdown = [], []
        for i in range(self.grid.npts):
            r = self.grid.pts.rad[i]
            if r <= self.grid.well.r:
                r = self.grid.pts.rad[i-1]
            dd = self.disp(r, self.aq.S, self.aq.T, t, self.well.q)
            radius.append(r)
            drawdown.append(dd)
        # Plot results
        mid_row = int(self.grid.grdim/2)
        if plot:
            cm = plt.cm.get_cmap('Blues').reversed()
            fig, (ax1, ax2) = plt.subplots(
            2, 1, gridspec_kw={'height_ratios': [4, 1]}, figsize=(6, 7.6)
            )
            fig.suptitle(plot_title, fontsize=14)
            fig.suptitle(plot_title, fontsize=14)
            ax1.tricontourf(x, y, drawdown, cmap=cm)
            cs = ax1.tricontour(
                x, y, drawdown, linewidths=0.25, colors=['black']
            )
            ax1.clabel(cs, inline=1, fontsize=10)
            ax1.plot(wx, wy, '.', c='red')
            ax1.set_title('Displacement Contours')
            ax1.grid(True)
            ax1.axis('equal')
            ax2.plot(
                x[self.grid.grdim*(mid_row-1):self.grid.grdim*mid_row],
                drawdown[self.grid.grdim*(mid_row-1):self.grid.grdim*mid_row],
                '.-', lw=3, alpha=0.5
            )
            ax2.set_title('Radial Displacement')
            ax2.grid(True)
            plt.show()
            plt.close()
        # Export result
        df = pandas.DataFrame()
        df['x'] = x
        df['y'] = y
        df['radius'] = radius
        df['drawdown'] = drawdown
        if csv != '':
            if csv.split('.') != 'csv':
                csv = csv + '.csv'
            df.to_csv(csv, index=False)
            print('Results exported to:', csv)
        if xlsx != '':
            if xlsx.split('.') != 'xlsx':
                xlsx = xlsx + '.xlsx'
            df.to_excel(xlsx, sheet_name='drawdown', index=False)
            print('Results exported to:', xlsx)
        return df


from kivy.uix.boxlayout import BoxLayout
from kivy.uix.image import AsyncImage
from kivy.uix.stacklayout import StackLayout
from kivy.lang.builder import Builder
from kivy.properties import NumericProperty
from kivy.app import App
from discord import TextChannel
from kivy.uix.button import Button
from kivy.clock import Clock
from functools import partial

Builder.load_string("""<ServerWidget>:
    orientation: 'horizontal'
    canvas:
        Color:
            rgb: 30/255, 31/255, 34/255
        Rectangle:
            size: self.size
            pos: self.pos
    ScrollView:
        size_hint_x: 0.2
        GuildWidget:
            spacing: '8dp'
            size_hint_y: None
            height: self.minimum_height
            id: guild
    ChannelWidget:
        id: channel

<-CircleImage>:
    size_hint: (1, None)
    height: self.width
    canvas:
        Color:
            rgb: (1, 1, 1)
        Ellipse:
            texture: self.texture
            size: self.size
            pos: self.pos

<ChannelWidget>:
    orientation: 'vertical'
    spacing: '10sp'
    canvas:
        Color:
            rgb: 43/255, 45/255, 49/255
        RoundedRectangle:
            size: self.size
            pos: self.pos
    Label:
        bold: True
        size_hint: (1, 0.1)
        font_size: '20dp'
        text_size: self.size
        halign: 'center'
        valign: 'center'
        id: label
    ScrollView:
        StackLayout:
            size_hint: 1, None
            spacing: '10sp'
            height: self.minimum_height
            id: layout

<ChannelButton>:
    size_hint: (1, None)
    font_size: '15sp'
    text_size: self.width, None
    height: self.texture_size[1]
    background_color: (1,1,1,0)
    foreground_color: (128/255, 132/255, 142/255)
""")

class GuildWidget(StackLayout):
    pass

class CircleImage(AsyncImage):
    guild_id = NumericProperty(0)

    def __init__(self, **kwargs):
        if 'source' in kwargs:
            kwargs['source'] = kwargs['source'].partition('?')[0]

        super().__init__(**kwargs)

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            App.get_running_app().discord_client.set_server.start(self.guild_id)
        return False

class ServerWidget(BoxLayout):
    def set_servers(self, guilds):
        guild_widget: GuildWidget = self.ids['guild']
        guild_widget.clear_widgets()

        for guild in guilds:
            icon = guild.icon
            url = icon.url.partition('?')[0]

            def lol(url, id, _):
                circle = CircleImage(source=url, guild_id=id)
                guild_widget.add_widget(circle)

            Clock.schedule_once(partial(lol, url, guild.id))

    def set_server(self, guild):
        channel = self.ids['channel']
        label = channel.ids['label']

        label.text = guild.name

        layout: StackLayout = channel.ids['layout']

        layout.clear_widgets()

        for channel in guild.channels:
            if not isinstance(channel, TextChannel):
                continue

            if not channel.permissions_for(guild.me).read_message_history:
                continue

            button = ChannelButton(channel_id=channel.id, text=channel.name)

            layout.add_widget(button)

class ChannelButton(Button):
    channel_id = NumericProperty(0)

    def on_press(self):
        app = App.get_running_app()
        app.discord_client.set_channel.start(self.channel_id)

class ChannelWidget(BoxLayout):
    pass


import json
import cv2
import numpy as np
from PIL import Image
from torch.utils import data as data

class ImageData(data.Dataset):
    def __init__(self, files, trans, trans2, tokenizer):
        super(ImageData, self).__init__()
        self.files = files
        self.vae_transforms = trans
        self.yolo_transforms = trans2
        self.tokenizer = tokenizer

    @staticmethod
    def load_prompt(json_path):
        with open(json_path, 'r') as json_file:
            data = json.load(json_file)
        prompt = data['title']
        return prompt

    def __getitem__(self, data_index):
        try:
            # load image
            image = Image.open(self.files[data_index]).convert("RGB")
            detector_input = cv2.cvtColor(np.array(image), cv2.COLOR_BGR2RGB)
            pixel_values = self.vae_transforms(image)
            detector_input = self.yolo_transforms(detector_input)

            # load prompt
            prompt_path = self.files[data_index].replace('.jpg', '.json')
            prompt = self.load_prompt(prompt_path)

            inputs = self.tokenizer(
                prompt, max_length=self.tokenizer.model_max_length,
                padding="do_not_pad",
                truncation=True
            )
            input_ids = inputs.input_ids

        except Exception as e:
            print(self.files[data_index], e)
            return None

        return {
            "pixel_values": pixel_values,
            "detector_input": detector_input,
            "input_ids": input_ids,
        }

    def __len__(self):
        return len(self.files)


from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals

import collections
import shlex

class CommandStringParser(object):
  """Object which builds and returns all metadata about string and flags.

  Attributes:
    command_node: calliope._CommandCommon, The command object that has access
    to argparse.
    command_parser: The argparse object for command_node.
    example_string: The most recently parsed example command string.
    example_metadata: The metadata gotten from example_string.
  """

  def __init__(self, command_node):
    self.command_node = command_node
    self.command_parser = self.command_node._parser

  def parse(self, example_command_string):
    """Gets relevant metadata from an example command string.

    Args:
      example_command_string: The example command string to be parsed.

    Returns:
      An ExampleCommandMetadata object containing the relevant metadata or None
      if there was a parsing error.
    """
    self.example_string = example_command_string
    self.example_metadata = ExampleCommandMetadata()

    parse_input = self.get_parse_args(example_command_string)
    if not parse_input:
      return

    metadata = self.command_parser.parse_args(parse_input, raise_error=True)
    filtered = metadata.GetSpecifiedArgsDict()

    for key, value in filtered.items():
      tmp_value = getattr(metadata, key, None)
      if isinstance(tmp_value, list):
        self.parse_list(tmp_value, key, value)

      elif isinstance(tmp_value, collections.OrderedDict):
        self.parse_dict(tmp_value, key, value)

      else:
        self.parse_others(tmp_value, key, value)

    return self.example_metadata

  def parse_dict(self, dict_arg, key, value, prev_stop=0, count=None):
    """Gets metadata from an example command string for a simple dict-type arg.

    It updates the already existing ExampleCommandMetadata object of the example
    string with the metadata.

    Args:
      dict_arg: The dictionary-type argument to collect metadata about.
      key: The name of the argument's attribute in the example string's
      namespace.
      value: The actual input representing the flag/argument in the example
      string (e.g --zone, --shielded-secure-boot).
      prev_stop: Optional. The index in the example string the flag was last
      seen.
      count: Optional. The number of times the flag has been seen in the example
      string.

    Returns:
      The index in the example string where parsing stopped if the argument is
      specified multiple times.
    """
    dict_list = list(dict_arg.items())
    first_pair = dict_list[0]
    last_pair = dict_list[-1]

    start_search = self.get_start_search(value, prev_stop)
    start_index = self.example_string.index(str(first_pair[0]), start_search)

    next_start = self.example_string.find('--', start_index)
    if next_start < start_search: next_start = len(self.example_string)
    last_value = str(last_pair[1])
    last_value_start = self.example_string.rfind(last_value, start_search,
                                                 next_start)
    stop_index = last_value_start + len(last_value) - 1

    arg_value = self.example_string[start_index:stop_index+1]
    # If count, dict_arg is part of a list and arg's action is append.
    # Otherwise, it's a normal dictionary arg.
    scope = '{key}_{count}'.format(key=key, count=count) if count else key
    arg_metadata = ArgumentMetadata(key, arg_value, scope,
                                    start_index, stop_index)
    self.example_metadata.add_arg_metadata(arg_metadata)

    if count:
      return arg_metadata.stop_index + 1

  def parse_list(self, list_arg, key, value, prev_stop=0, count=None):
    """Gets metadata from an example command string for a list-type argument.

    It updates the already existing ExampleCommandMetadata object of the example
    string with the metadata.

    Args:
      list_arg: The list-type argument to collect metadata about.
      key: The name of the argument's attribute in the example string's
      namespace.
      value: The actual input representing the flag/argument in the example
      string (e.g --zone, --shielded-secure-boot).
      prev_stop: Optional. The index in the example string the flag was last
      seen.
      count: Optional. The number of times the flag has been seen in the example
      string.

    Returns:
      The index in the example string where parsing stopped if the argument is
      specified multiple times.
    """
    if isinstance(list_arg[0], collections.OrderedDict):
      self.parse_nested_list(list_arg, key, value)

    elif isinstance(list_arg[0], list):
      self.parse_nested_list(list_arg, key, value)

    else:
      # Assumes list elements are either strings or numbers; excludes booleans.

      start_search = self.get_start_search(value, prev_stop)
      start_index = self.example_string.index(str(list_arg[0]), start_search)

      next_start = self.example_string.find('--', start_index)
      if next_start < start_search or next_start == -1:
        next_start = len(self.example_string)
      last_value = str(list_arg[-1])
      last_value_start = self.example_string.rfind(last_value, start_search,
                                                   next_start)
      stop_index = last_value_start + len(last_value) -1
      arg_value = self.example_string[start_index:stop_index+1]
      scope = '{key}_{count}'.format(key=key, count=count) if count else key
      # count implies list_arg is an inner list which implies action is append.
      # no count implies simple list which implies action is update.

      arg_metadata = ArgumentMetadata(key, arg_value, scope, start_index,
                                      stop_index)
      self.example_metadata.add_arg_metadata(arg_metadata)

      if count:
        return arg_metadata.stop_index + 1

  def parse_nested_list(self, list_arg, key, value):
    """Gets metadata from an example command string for nested list arguments.

    This is a helper function for parse_list().

    It updates the already existing ExampleCommandMetadata object of the example
    string with the metadata.

    Args:
      list_arg: The list-type argument to collect metadata about.
      key: The name of the argument's attribute in the example string's
      namespace.
      value: The actual input representing the flag/argument in the example
      string (e.g --zone, --shielded-secure-boot).
    """
    flag_count = self.example_string.count(value)
    if isinstance(list_arg[0], collections.OrderedDict):
      # Flag specified once in example string and occurs multiple times in
      # namespace implies flag was specified with custom delimiter.
      if flag_count == 1 and len(list_arg) > 1:
        first_dict = list(list_arg[0].items())
        last_dict = list(list_arg[-1].items())
        start = first_dict[0][0]  # first key of first dictionary
        stop = last_dict[-1][1]  # last key of last dictionary

        start_search = self.get_start_search(value)
        start_index = self.example_string.index(str(start), start_search)
        next_start = self.example_string.find('--', start_index)
        if next_start < start_search: next_start = len(self.example_string)
        stop_index = (self.example_string.rfind(str(stop), start_search,
                                                next_start) +
                      len(str(stop)) - 1)

        arg_value = self.example_string[start_index:stop_index+1]
        arg_metadata = ArgumentMetadata(key, arg_value, key, start_index,
                                        stop_index)
        self.example_metadata.add_arg_metadata(arg_metadata)

      # Flag specified multiple times in both example string namespace implies
      # flag's action is append.
      else:
        prev_stop = 0
        for i in range(flag_count):
          val = list_arg[i]
          prev_stop = self.parse_dict(val, key, value, prev_stop, i+1)

    # Nested list(list_arg[0] is a list) implies action is append.
    else:
      prev_stop = 0
      for i in range(flag_count):
        val = list_arg[i]
        prev_stop = self.parse_list(val, key, value, prev_stop, i+1)

  def parse_others(self, other_arg, key, value):
    """Gets metadata from an example string for non list-type/dict-type args.

    It updates the already existing ExampleCommandMetadata object of the example
    string with the metadata.

    Args:
      other_arg: The non list-type and non dict-type argument to collect
      metadata about.
      key: The name of the argument's attribute in the example string's
      namespace.
      value: The actual input representing the flag/argument in the example
      string (e.g --zone, --shielded-secure-boot).

    """
    # Editable range excludes quotes and booleans.

    if not isinstance(other_arg, bool):
      start_search = self.get_start_search(value)
      start_index = self.example_string.find(str(other_arg), start_search)
      if start_index == -1:
        #  Enum type
        other_arg = self.get_enum_value(other_arg, start_search)

      start_index = self.example_string.index(str(other_arg), start_search)
      arg_metadata = ArgumentMetadata(key, other_arg, key, start_index,
                                      start_index + len(str(other_arg)) - 1)

      self.example_metadata.add_arg_metadata(arg_metadata)

  def get_enum_value(self, enum_value, prev_stop):
    """Gets the input value of an enum argument in the example string.

    This is a helper function for parse_others().

    Args:
      enum_value: The namespace value of the argument in question.
      prev_stop: The index in the example string where parsing stopped.

    Returns:
     The actual input in the example string representing the argument's value.
    """
    unparsed_string = self.example_string[prev_stop:]

    if isinstance(enum_value, str):
      #  Check for common variations(underscore/hypen; lower/upper)
      possible_versions = [enum_value.lower(), enum_value.upper(),
                           enum_value.replace('-', '_'),
                           enum_value.replace('_', '-')]
      for version in possible_versions:
        if version in unparsed_string:
          enum_value = version

    if str(enum_value) not in unparsed_string:
      unparsed_string = unparsed_string.strip()
      arg_end = unparsed_string.find(' --')
      # Keep last character if we are at the end of the example.
      arg_list = (unparsed_string[:arg_end].split('=') if arg_end != -1
                  else unparsed_string.split('='))

      enum_value = (' '.join(arg_list[1:]).strip() if len(arg_list) > 2 else
                    arg_list[-1].strip())
      # We'll strip the whitespace so it won't be part of the argument value.

    return enum_value

  def get_start_search(self, namespace_name, prev_stop=0):
    """Gets the position to begin searching for an argument's value.

    This is a helper function for all the parse functions aside from parse().

    Args:
      namespace_name: The value of the argument in namespace's specified_args
      dictionary. ('INSTANCE_NAMES:1', '--zone', etc)
      prev_stop: Optional. For recurring flags, where the flag was last
      seen.

    Returns:
      The index in the example string to begin searching.
    """
    # Start searching for value from --{flag_name} if it occurs once
    # or --{flag_name} after the last place the flag was seen if it
    # occurs multiple times.
    if prev_stop:
      start_search = (self.example_string.find(namespace_name, prev_stop) +
                      len(namespace_name))
    else:
      start_search = (self.example_string.find(namespace_name) +
                      len(namespace_name))

    # For positional arguments in list form, start searching from after the
    # command name.
    if start_search == -1:
      command_name = self.command_node.name.replace('_', '-')
      command_name_start = self.example_string.find(command_name)
      start_search = command_name_start + len(command_name)+ 1

    return start_search

  def get_parse_args(self, string):
    """Gets a list of arguments in a string.

    (Note: It assumes '$' is not included in the string)

    Args:
      string: The string in question.

    Returns:
      A list of the arguments from the string.
    """
    command_name = self.command_node.name.replace('_', '-')
    command_name_start = string.find(command_name)

    # Return None if command string is under a different command node.
    if command_name_start == -1:
      return

    # calculation includes the space after the command string.
    command_name_stop = command_name_start + len(command_name)+ 1
    args_list = shlex.split(string[command_name_stop:])

    return args_list

class ExampleCommandMetadata(object):
  """Encapsulates metadata about entire example command string.

  Attributes:
    argument_metadatas: A list containing the metadata for each argument in an
    example command string.
  """

  def __init__(self):
    self._argument_metadatas = []

  def add_arg_metadata(self, arg_metadata):
    """Adds an argument's metadata to comprehensive metadata list.

    Args:
      arg_metadata: The argument metadata to be added.
    """
    self._argument_metadatas.append(arg_metadata)

  def get_argument_metadatas(self):
    """Returns the metadata for an entire example command string."""
    return sorted(self._argument_metadatas, key=lambda x: x.stop_index)

  def __eq__(self, other):
    if isinstance(other, ExampleCommandMetadata):
      # sort both first
      our_data = sorted(self._argument_metadatas, key=lambda x: x.stop_index)
      other_data = sorted(other._argument_metadatas, key=lambda x: x.stop_index)

      if len(our_data) != len(other_data):
        return False

      for i in range(len(self._argument_metadatas)):
        if our_data[i] != other_data[i]:
          return False
      return True

    return False

  def __ne__(self, other):
    return self.__eq__(other)

  def __str__(self):
    metadatas = self.get_argument_metadatas()
    result = [str(data) for data in metadatas]
    return '[{result}]'.format(result=',  '.join(result))

class ArgumentMetadata(object):
  """Encapsulates metadata about a single argument.

  Attributes:
    arg_name: The name of the argument.
    arg_value: Value of the argument.
    scope: The scope of the argument.
    start_index: The  index where the argument starts in the command string.
    stop_index: The index where the argument stops in the command string.
  """

  def __init__(self, arg_name, arg_value, scope, start_index, stop_index):
    self.arg_name = arg_name
    self.arg_value = arg_value
    self.scope = scope
    self.start_index = start_index
    self.stop_index = stop_index

  def __str__(self):
    """Returns a human-readable representation of an argument's metadata."""
    return ('ArgumentMetadata(name={name},  value={value},  scope={scope},  '
            'start_index={start},  stop_index='
            '{stop})').format(name=self.arg_name, scope=self.scope,
                              value=self.arg_value, start=self.start_index,
                              stop=self.stop_index)

  def __eq__(self, other):
    if isinstance(other, ArgumentMetadata):
      return (self.arg_name == other.arg_name and
              self.arg_value == other.arg_value and
              self.scope == other.scope and
              self.start_index == other.start_index and
              self.stop_index == other.stop_index)

    return False

  def __ne__(self, other):
    return not self.__eq__(other)


# iotest.py Test PR #3836 timing using GPIO pins.

import io, pyb
import uasyncio as asyncio
import micropython
micropython.alloc_emergency_exception_buf(100)

MP_STREAM_POLL = const(3)
MP_STREAM_POLL_RD = const(1)

y1 = pyb.Pin('Y1', pyb.Pin.OUT)

class MyIO(io.IOBase):
    def __init__(self):
        self.ready = False
        self.count = 0
        tim = pyb.Timer(4)
        tim.init(freq=1)  # 1Hz - 1 simulated input line per sec.
        tim.callback(self.setready)

    def ioctl(self, req, arg):
        if req == MP_STREAM_POLL and (arg & MP_STREAM_POLL_RD):
            state = pyb.disable_irq()
            r = self.ready
            self.ready = False
            pyb.enable_irq(state)
            return r
        return 0

    def readline(self):  # Y1 goes low when I/O is serviced
        y1.value(0)
        return '{}\n'.format(self.count)

    def setready(self, t):  # Y1 goes high when I/O becomes ready
        self.count += 1
        y1.value(1)
        self.ready = True

myio = MyIO()

async def foo(p):  # Toggle a pin when scheduled
    print('start foo', p)
    pin = pyb.Pin(p, pyb.Pin.OUT)
    while True:
        pin.value(1)
        await asyncio.sleep(0)
        pin.value(0)
        await asyncio.sleep(0)

async def receiver():
    last = None
    nmissed = 0
    sreader = asyncio.StreamReader(myio)
    while True:
        res = await sreader.readline()
        print('Recieved {} Missed {}'.format(res, nmissed))
        ires = int(res)
        if last is not None:
            if last != ires -1:
                print('Missed {}'.format(ires - 1))
                nmissed += 1
        last = ires

loop = asyncio.get_event_loop()
loop.create_task(receiver())
loop.create_task(foo('Y2'))
loop.create_task(foo('Y3'))
loop.run_forever()


from bs4 import BeautifulSoup
from urllib.request import urlretrieve
import os
import time
import requests

if __name__ == '__main__':
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
    }
    # List Urls
    url = 'http://www.itmtu.net/wh/hong.html'
    req = requests.get(url=url, headers=headers)
    req.encoding = 'utf-8'
    html = req.text
    bf = BeautifulSoup(html, 'lxml')
    targets_url = bf.find_all(class_='fl_link')
    lists_url = []
    # '93', '349'
    tag_list = ['400','224','371','235','430','107','403','390','324','389','69','407','96','238','40','313','272','312','19','66','422','98','94','176','387']
    for each in targets_url:
        temp = each.get('href')
        if each.get('data-tag') in tag_list and isinstance(temp, str) and temp[0] == '/' and temp[1] == 't':
            lists_url.append('http://www.itmtu.net' + each.get('href'))

    # Person Urls
    for list_ in lists_url:
        req = requests.get(url=list_, headers=headers)
        req.encoding = 'utf-8'
        html = req.text
        bf = BeautifulSoup(html, 'lxml')
        temp_url = bf.find_all(class_='page-numbers')
        person_url = bf.find(class_='demo2-large') # Get the person's name
        if isinstance(person_url.get_text(),str):
            person_name = person_url.get_text()[5:]
        if person_name not in os.listdir('images'):
            os.makedirs('images/'+person_name) # make a folder for the person
        pages_url = [list_] # Initialize pages_url by putting list_ as the first page url
        for i in temp_url:
            if isinstance(i.get('href'),str):
                pages_url.append('http://www.itmtu.net' + i.get('href'))
        for page in pages_url:
            page_req = requests.get(url=page, headers=headers)
            page_req.encoding = 'utf-8'
            page_html = page_req.text
            page_bf = BeautifulSoup(page_html,'lxml')
            del temp_url
            temp_url = page_bf.find_all(class_='meta-title')
            sets_url = []
            for temp in temp_url:
                if isinstance(temp.get('href'),str) and isinstance(temp.get_text(),str):
                    sets_url.append(temp.get_text()+'=http://www.itmtu.net' + temp.get('href'))
            for set_ in sets_url:
                set_url = set_.split("=")[1]
                set_name = set_.split("=")[0]
                set_req = requests.get(url=set_url,headers=headers)
                set_req.encoding = 'utf-8'
                set_html=set_req.text
                set_bf = BeautifulSoup(set_html,'lxml')
                set_finalpage = set_bf.find(title="最后页")
                if set_finalpage != None:
                    set_pagenum = set_finalpage.get_text()
                else:
                    set_pagenum = 0
                pics_url = []
                for i in range(int(set_pagenum)):
                    set_page_url = set_url+str(i+1)
                    set_page_req = requests.get(url=set_page_url,headers=headers)
                    set_page_req.encoding = 'utf-8'
                    set_page_html = set_page_req.text
                    set_page_bf = BeautifulSoup(set_page_html, 'lxml')
                    pic_url = set_page_bf.find(class_='image_div')
                    pics_url.append(pic_url.img.get('alt')+ '=' + pic_url.img.get('src'))
                filename = os.getcwd()+ '/images/' + person_name + '/' + set_name + '.txt'
                with open(filename, 'w') as f:
                    for item in pics_url:
                        f.write("%s\n" % item)
                print('finished downloading: ' + filename)
                time.sleep(5)
    print('End of the program')


# Prim's algorithm #
# Time: O(N^2 * log(N))
# Space: O(N^2)
import heapq
from collections import defaultdict
points=[[0,0],[2,2],[3,10],[5,2],[7,0]]
N=len(points)
#https://leetcode.com/problems/min-cost-to-connect-all-points/solution/
### Actually dont even need adjacency list
adj=defaultdict(list)
for i in range(N):
    for j in range(i+1,N):
        cost = abs(points[i][0]-points[j][0]) + abs(points[i][1]-points[j][1])
        adj[i].append([cost,j])
        adj[j].append([cost,i])
h=[[0,0]]
visited=set()
res=0
# while h:
c=0
while len(visited)<N: # This is more optimized
# while h:
    c+=1
    cost, node = heapq.heappop(h)
    if node in visited:
        continue
    visited.add(node)
    res+=cost
    for childcost, child in adj[node]:
        if child not in visited:
            heapq.heappush(h,[childcost,child])
print(res,c)


# Title:      Medium Asteroid Class
# Filename:   medium.py
# Purpose:    Creates a
#             class for a
#             medium asteroid
#             object to be used in
#             the asteroid program.
# Date:       03/01/2021
###############################################
import arcade
import constants
import math
import random
from asteroid import Asteroid
from small import SmallAsteroid

class MediumAsteroid(Asteroid):
    """
    Initializes a medium
    asteroid.
    """
    def __init__(self, large_rock, order):
        super().__init__()
        self.img       = "images\meteorGrey_med1.png"
        self.texture   = arcade.load_texture(self.img)
        self.height    = self.texture.height
        self.width     = self.texture.width
        self.radius    = constants.MEDIUM_ROCK_RADIUS
        self.speed     = constants.BIG_ROCK_SPEED
        self.center.x  = large_rock.center.x
        self.center.y  = large_rock.center.y
        self.direction = large_rock.direction
        self.type      = constants.ASTRD_MD_TYPE

        if order == 1:
            # The first medium asteroid has the same velocity as the
            # original large one plus 2 pixel/frame in the up direction.
            self.velocity.dx = large_rock.velocity.dx
            self.velocity.dy = large_rock.velocity.dy + constants.MEDIUM_ROCK_DY1
        else:
            # The second medium asteroid has the same velocity as the
            # original large one plus 2 pixel/frame in the down direction.
            self.velocity.dx = large_rock.velocity.dx
            self.velocity.dy = large_rock.velocity.dy - constants.MEDIUM_ROCK_DY1

    def hit(self):
        """
        Updates the score
        and breaks up a
        large asteroid into
        smaller asteroids.
        """

        self.alive = False
        return self.points

    def break_apart(self):
        """
        Medium asteroids
        break apart
        into two small
        asteroids.
        """
        two_small_asteroids = []
        asteroid_sma2 = SmallAsteroid(self, 2)
        asteroid_sma3 = SmallAsteroid(self, 3)
        two_small_asteroids.append(asteroid_sma2)
        two_small_asteroids.append(asteroid_sma2)
        return two_small_asteroids


from abc import ABC, abstractmethod

import attrs

from data_diff.abcs.database_types import (
    Array,
    TemporalType,
    FractionalType,
    ColType_UUID,
    Boolean,
    ColType,
    String_UUID,
    JSON,
    Struct,
)
from data_diff.abcs.compiler import Compilable

@attrs.define(frozen=False)
class AbstractMixin(ABC):
    "A mixin for a database dialect"

@attrs.define(frozen=False)
class AbstractMixin_NormalizeValue(AbstractMixin):
    @abstractmethod
    def to_comparable(self, value: str, coltype: ColType) -> str:
        """Ensure that the expression is comparable in ``IS DISTINCT FROM``."""

    @abstractmethod
    def normalize_timestamp(self, value: str, coltype: TemporalType) -> str:
        """Creates an SQL expression, that converts 'value' to a normalized timestamp.

        The returned expression must accept any SQL datetime/timestamp, and return a string.

        Date format: ``YYYY-MM-DD HH:mm:SS.FFFFFF``

        Precision of dates should be rounded up/down according to coltype.rounds
        """

    @abstractmethod
    def normalize_number(self, value: str, coltype: FractionalType) -> str:
        """Creates an SQL expression, that converts 'value' to a normalized number.

        The returned expression must accept any SQL int/numeric/float, and return a string.

        Floats/Decimals are expected in the format
        "I.P"

        Where I is the integer part of the number (as many digits as necessary),
        and must be at least one digit (0).
        P is the fractional digits, the amount of which is specified with
        coltype.precision. Trailing zeroes may be necessary.
        If P is 0, the dot is omitted.

        Note: We use 'precision' differently than most databases. For decimals,
        it's the same as ``numeric_scale``, and for floats, who use binary precision,
        it can be calculated as ``log10(2**numeric_precision)``.
        """

    def normalize_boolean(self, value: str, _coltype: Boolean) -> str:
        """Creates an SQL expression, that converts 'value' to either '0' or '1'."""
        return self.to_string(value)

    def normalize_uuid(self, value: str, coltype: ColType_UUID) -> str:
        """Creates an SQL expression, that strips uuids of artifacts like whitespace."""
        if isinstance(coltype, String_UUID):
            return f"TRIM({value})"
        return self.to_string(value)

    def normalize_json(self, value: str, _coltype: JSON) -> str:
        """Creates an SQL expression, that converts 'value' to its minified json string representation."""
        return self.to_string(value)

    def normalize_array(self, value: str, _coltype: Array) -> str:
        """Creates an SQL expression, that serialized an array into a JSON string."""
        return self.to_string(value)

    def normalize_struct(self, value: str, _coltype: Struct) -> str:
        """Creates an SQL expression, that serialized a typed struct into a JSON string."""
        return self.to_string(value)

    def normalize_value_by_type(self, value: str, coltype: ColType) -> str:
        """Creates an SQL expression, that converts 'value' to a normalized representation.

        The returned expression must accept any SQL value, and return a string.

        The default implementation dispatches to a method according to `coltype`:

        ::

            TemporalType    -> normalize_timestamp()
            FractionalType  -> normalize_number()
            *else*          -> to_string()

            (`Integer` falls in the *else* category)

        """
        if isinstance(coltype, TemporalType):
            return self.normalize_timestamp(value, coltype)
        elif isinstance(coltype, FractionalType):
            return self.normalize_number(value, coltype)
        elif isinstance(coltype, ColType_UUID):
            return self.normalize_uuid(value, coltype)
        elif isinstance(coltype, Boolean):
            return self.normalize_boolean(value, coltype)
        elif isinstance(coltype, JSON):
            return self.normalize_json(value, coltype)
        elif isinstance(coltype, Array):
            return self.normalize_array(value, coltype)
        elif isinstance(coltype, Struct):
            return self.normalize_struct(value, coltype)
        return self.to_string(value)

@attrs.define(frozen=False)
class AbstractMixin_MD5(AbstractMixin):
    """Methods for calculating an MD6 hash as an integer."""

    @abstractmethod
    def md5_as_int(self, s: str) -> str:
        "Provide SQL for computing md5 and returning an int"

@attrs.define(frozen=False)
class AbstractMixin_Schema(AbstractMixin):
    """Methods for querying the database schema

    TODO: Move AbstractDatabase.query_table_schema() and friends over here
    """

    def table_information(self) -> Compilable:
        "Query to return a table of schema information about existing tables"
        raise NotImplementedError()

    @abstractmethod
    def list_tables(self, table_schema: str, like: Compilable = None) -> Compilable:
        """Query to select the list of tables in the schema. (query return type: table[str])

        If 'like' is specified, the value is applied to the table name, using the 'like' operator.
        """

@attrs.define(frozen=False)
class AbstractMixin_RandomSample(AbstractMixin):
    @abstractmethod
    def random_sample_n(self, tbl: str, size: int) -> str:
        """Take a random sample of the given size, i.e. return 'size' amount of rows"""

    @abstractmethod
    def random_sample_ratio_approx(self, tbl: str, ratio: float) -> str:
        """Take a random sample of the approximate size determined by the ratio (0..1), where 0 means no rows, and 1 means all rows

        i.e. the actual mount of rows returned may vary by standard deviation.
        """

    # def random_sample_ratio(self, table: ITable, ratio: float):
    #     """Take a random sample of the size determined by the ratio (0..1), where 0 means no rows, and 1 means all rows
    #     """

@attrs.define(frozen=False)
class AbstractMixin_TimeTravel(AbstractMixin):
    @abstractmethod
    def time_travel(
        self,
        table: Compilable,
        before: bool = False,
        timestamp: Compilable = None,
        offset: Compilable = None,
        statement: Compilable = None,
    ) -> Compilable:
        """Selects historical data from a table

        Parameters:
            table - The name of the table whose history we're querying
            timestamp - A constant timestamp
            offset - the time 'offset' seconds before now
            statement - identifier for statement, e.g. query ID

        Must specify exactly one of `timestamp`, `offset` or `statement`.
        """

@attrs.define(frozen=False)
class AbstractMixin_OptimizerHints(AbstractMixin):
    @abstractmethod
    def optimizer_hints(self, optimizer_hints: str) -> str:
        """Creates a compatible optimizer_hints string

        Parameters:
            optimizer_hints - string of optimizer hints
        """