"""
>> LOGIC FUNCTIONS FOR CLIENTS
"""

from django.shortcuts import render,  redirect
from django.contrib.auth.decorators import login_required
from clientsapp.models import Clients
from .forms import ClientForm
from django.db.models import Q
import datetime
import openpyxl
from django.http import HttpResponse
# pass - admin - 123
# pass - hruser - 123

# HOME -> FORM DISPLAY - ADD CLIENT - UPDATE CLIENT
@login_required(login_url='loginPage')
def home(request, id=0):
    if request.method == "GET":
        auth_user = request.user.first_name
        all_clients = Clients.objects.all()

        male_count = Clients.objects.filter(gender='M').count()
        female_count = Clients.objects.filter(gender='F').count()
        other_count = Clients.objects.filter(gender='O').count()
        print("Male count:", male_count)
        print(female_count)
        print(other_count)
        gender_count  = [male_count , female_count , other_count]
        gender_name = ["Male" , "Female" , "Others"]

        if id == 0:
            form = ClientForm()
        else:
            client = Clients.objects.get(pk=id)
            form = ClientForm(instance=client)
        context = {"auth_user": auth_user,
                   "page": "HOME | CLIENT | Edify Lab's Business Tool ", "ClientForm": form, "total_clients":  len(all_clients) , "gender_count" : gender_count , "gender_name" : gender_name }
        return render(request, "home.html", context)
    else:
        if id == 0:
            form = ClientForm(request.POST)
        else:
            client = Clients.objects.get(pk=id)
            form = ClientForm(request.POST, instance=client)
        if form.is_valid():
            form.save()

        return redirect('/clients-list/')

# DISPLAYS ALL CLIENTS
@login_required(login_url='loginPage')
def clients_list(request):
    all_clients = Clients.objects.all()
    page = "All clients | Edify Lab's Business Tool"
    if len(all_clients) != 0:
        context_clients_list = {
            "clients_list": all_clients, "total_clients": len(all_clients) , "page" : page}
    else:
        error = "NO SILENTS 0"
        context_clients_list = {"error": error  , "page":page}
    return render(request, "clients_template/clients_list.html/", context_clients_list)

# DELETE A SELECTED CLIENT
@login_required(login_url='loginPage')
def item_delete(request):
    if request.method == 'POST':
        item_ids = request.POST.getlist('item_ids')
        print(item_ids , "SELECTED")
        if item_ids:
            Clients.objects.filter(id__in=item_ids).delete()
    return redirect('/clients-list/')

# SEARCH CLIENT -> FNAME , LNAME , EMAIL , COURSE
@login_required(login_url='loginPage')
def search_client(request):
    if request.method == "POST":
        page = "Search clients | Edify Lab's Business Tool"
        title = request.POST["title"]

        lookups = Q(first_name__icontains=title) | Q(
            coaching_type_course__title__icontains=title) | Q(last_name__icontains=title) | Q(email_id__icontains=title)
        filter_title = Clients.objects.filter(lookups)

        print(len(filter_title), lookups)
        if title != '' and title is not None and len(filter_title) != 0:

            context_clients_list = {
                "clients_list": Clients.objects.all(), "filter_title": filter_title, "filter_title_total": len(filter_title) , "page":page}
        else:
            error = "NO MATCH FOUND"
            context_clients_list = {"error": error , "page":page}
        return render(request, "clients_template/clients_list.html/", context_clients_list)
    else:
        print("---------------SOMETHING WENT WRONG IN SEARCH CLIENT-----------------------")
        return redirect('/home/')

# DOWNLOAD TO PDF
@login_required(login_url='loginPage')
def download_client(request, id):
    if request.method == "GET":
        auth_user = request.user.first_name
        client = Clients.objects.get(pk=id)
        now = datetime.datetime.now
        context = {"auth_user": auth_user,
                   "page": f"EdifyLabs | download - {client.first_name}-{client.last_name}-{client.id}", "clients": client, "DT": now}
        return render(request, "clients_template/download_client.html", context)

# DOWNLOAD TO EXCEL
def download_clients_excel(request):
    clients = Clients.objects.all()

    workbook = openpyxl.Workbook()
    sheet = workbook.active

    header_row = ["ID", "First Name", "Last Name", "Email", "Gender", "DOB" , "Address", "Contact" , "Company" ,"Course" ]
    sheet.append(header_row)

    for client in clients:
        data_row = [f"CL-{client.id}", client.first_name, client.last_name, client.email_id, client.gender, client.date_of_birth,client.address , client.contact , client.company_name, client.coaching_type_course.title]
        sheet.append(data_row)

    response = HttpResponse(content_type='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
    response['Content-Disposition'] = f'attachment; filename=clients_{datetime.datetime.now().strftime("%Y%m%d%H%M%S")}.xlsx'

    workbook.save(response)

    return response


"""
https://stepik.org/lesson/674986/step/14?unit=673426

Функция group_anagrams()
Анаграммы — это слова, которые состоят из одинаковых букв. Например:

адаптер — петарда
адресочек — середочка
азбука — базука
аистенок — осетинка
Реализуйте функцию group_anagrams(), которая принимает один аргумент:

words — список слов
Функция должна группировать в кортежи слова из списка words, являющиеся анаграммами, и возвращать список полученных кортежей.
"""

from itertools import groupby

def group_anagrams(words):
    g = groupby(sorted(words, key=sorted), key=sorted)
    for k, v in g:
        yield tuple(v)

Python for Professionals/10. Iterators & generators/part 11/step 14.py


from django.shortcuts import render, redirect
from .models import Boards
# Create your views here.
def index(request): # 메인페이지 전체 리스트
    b_all = Boards.objects.all()
    return render(request,'index.html', {'objects':b_all})

def new(request):
    return render(request,'new.html')

def create(request):
    title = request.GET['title']
    content = request.GET['contents']
    creator = request.GET['creator']
    #b = Boards(title= title , contents=content, creator = creator)
    #b.save()
    b = Boards.objects.create(title= title , contents=content, creator = creator)
    context = {
        'result': b
    }
    return redirect(f'/boards/{b.id}')

def show(request, id):
    board = Boards.objects.get(id=id)
    context={
        'result':board
    }
    return render(request,'show.html',context)
def edit(request , id):
    board = Boards.objects.get(id=id)
    context={
        'result':board
    }
    return render(request,'edit.html',context)
def update(request, id):
    board = Boards.objects.get(id=id)
    title = request.GET['title']
    content = request.GET['contents']
    creator = request.GET['creator']
    board.title = title
    board.contents =content
    board.creator = creator
    board.save()
    return redirect(f'/boards/{id}')
def destroy(request,id):
    board = Boards.objects.get(id=id)
    board.delete()
    return redirect('/boards/')


from markdown2 import Markdown
from jinja2 import Environment, FileSystemLoader

import datetime
import email.utils
import glob
import configparser

md = Markdown(extras=["fenced-code-blocks","metadata","task_list","tables","target-blank-links"])
templates = Environment(loader=FileSystemLoader("templates"))
src_folder = "Output"
out_folder = "docs"
md_files = glob.glob(f"./{src_folder}/*.md")
config = configparser.ConfigParser()
config.read("config.ini")

posts = []

def render_markdown_post(html,metadata=None,template="post.html",posts=[]):
	global templates
	return templates.get_template(template).render(content=html,posts=posts, config=config)

for md_file in md_files:
    with open(md_file) as f:
        _html = md.convert(f.read())
        _post_title = _html[4:_html.find("</h1>")]
        _post = _html.metadata
        _post["title"] = _post_title
        _post["link"] = md_file.replace(f"./{src_folder}","").replace("md","html")
        _post["pdf"] = md_file.replace(f"./{src_folder}","").replace("md","pdf")
        _html.metadata = _post
        print(_html.metadata)
        _html.metadata["description"] = _html.metadata["DESC"]
        _html.metadata["DATE"] = email.utils.format_datetime(datetime.datetime.strptime(_html.metadata["DATE"],"%Y-%m-%d %H:%M"))
        with open(md_file.replace(src_folder,out_folder).replace("md","html"),"w") as f:
            f.write(render_markdown_post(_html))

        posts.append(_html)

for pdf_file in glob.glob(f"./PDFs/*.pdf"):
    pdfbytes = open(pdf_file,"rb").read()
    with open(pdf_file.replace("PDFs","docs").replace("RENAMED - ",""),"wb") as f:
        f.write(pdfbytes)
with open(f"{out_folder}/index.html","w") as f:
    f.write(render_markdown_post(md.convert(open("index.md").read()),template="index.html",posts=posts))


'''
Author: lexcalibur
Date: 2021-12-09 17:41:26
LastEditors: lexcaliburr
LastEditTime: 2021-12-13 17:03:21
'''

import torch
import torch.nn.functional as F
import torch.nn as nn
import json

# torch.ops.load_library("/home/lishiqi/myrepos/MyCodeRepo/trt_deploy_demo/model/PluginDemo/torch_op/build/libhswish.so")

# 一个内置插件
class HSwishImplementation(torch.autograd.Function):
    @staticmethod
    def symbolic(g, input, weight, bias):
        b = torch.ones(1)
        return g.op("HSwish", input, weight, bias, b, info_s="string attribute", test_property_s="this is test", kernel_size_i=3, eps_f=3e-2)

    @staticmethod
    def forward(ctx, i, weight, bias):
        ctx.save_for_backward(i)
        # can call some cuda function
        return i * F.relu6(i + 3) / 6 + weight + bias

class MemoryEfficientHSwish(nn.Module):
    def __init__(self, shape):
        super(MemoryEfficientHSwish, self).__init__()
        self.bias = nn.Parameter(torch.zeros(shape))
        self.bias.data.fill_(3.15)
        self.weight = nn.Parameter(torch.zeros(shape))
        self.weight.data.fill_(99999)

    def forward(self, x):
        return HSwishImplementation.apply(x, self.weight, self.bias)

# 一个通过本框架实现的插件
class MReLUImplementation(torch.autograd.Function):
    @staticmethod
    def symbolic(g, input, bias):
        return g.op("Plugin", input, bias, name_s="MReLU", info_s=json.dumps({
            "kernel_size": 3,
            "eps": 3e-2,
            "other": "Hello Onnx Plugin"
        }))

    @staticmethod
    def forward(ctx, i, bias):
        ctx.save_for_backward(i)
        return F.relu(i) + bias

class MReLU(nn.Module):
    def __init__(self, *shape):
        super(MReLU, self).__init__()
        self.bias = nn.Parameter(torch.zeros(shape))
        self.bias.data.fill_(0.5)

    def forward(self, x):
        return MReLUImplementation.apply(x, self.bias)

class FooModel(torch.nn.Module):
    def __init__(self):
        super(FooModel, self).__init__()
        self.hswish = MemoryEfficientHSwish(1)
        self.mrelu = MReLU(1)

    def forward(self, input1, input2):
        return self.mrelu(input2) + self.hswish(input1)

dummy_input1 = torch.zeros((1, 3, 3, 3))
dummy_input2 = torch.zeros((1, 3, 3, 3))
model = FooModel()

dummy_input1[...] = 0.25
dummy_input2[...] = 0

# pt 1.10
# ONNX
# ONNX_ATEN
# ONNX_ATEN_FALLBACK
# ONNX_FALLTHROUGH

# pt 1.5.1
# ONNX
# ONNX_ATEN
# ONNX_ATEN_FALLBACK
# RAW

torch.onnx.export(model, (dummy_input1, dummy_input2),
                  '/home/lishiqi/myrepos/MyCodeRepo/trt_deploy_demo/model/PluginDemo/onnx/demo.onnx',
                  verbose=True,
                  enable_onnx_checker=True,
                  export_params=torch.onnx.OperatorExportTypes.ONNX_FALLTHROUGH)


import asyncio
import os
import random
import re
from PIL import Image
import aiohttp
import datetime
from bs4 import BeautifulSoup

import nonebot
from nonebot.adapters.cqhttp.bot import Bot
from nonebot.adapters.cqhttp.event import GroupMessageEvent, MessageEvent, PrivateMessageEvent
from nonebot.plugin import on_command, on_regex
from nonebot.rule import to_me
from nonebot.typing import T_State
from utils import NAME, image
from utils.image import ImgDraw
from utils.message_builder import image

from utils.message_builder import face, text
from utils.zhongguose import *

__usage__ = f'您可以使用任何正常状态下的文字请{NAME}算命'
__help__version__ = '0.1.4'
__help__plugin_name__ = "智能化八字算命"

bg = os.path.join('.', 'res', 'ft', 'bg.png')
font = os.path.join('.', 'res', 'fonts','LXGWWenKai-Regular.ttf')
Image.new('RGB', (1200, 3000), (255, 255, 255)).save(bg)

ft = on_regex(
    '.*(算.{0,2}[命卦]|卜.{0,2}卦).*', rule=to_me()
)

headers = {
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
    'Accept-Encoding': 'gzip, deflate',
    'Accept-Language': 'zh-CN,zh;q=0.9',
    'Content-Type': 'application/x-www-form-urlencoded',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/93.0.4577.82 Safari/537.36'
}

def is_all_zh(s):
    for c in s:
        if not ('\u4e00' <= c <= '\u9fa5'):
            return False
    return True

def processing_text(text: str, deletions: list = [], delete_space: bool = False, line_feed: bool = False):
    text = text.replace(u'\xa0', u' ').replace(u'\u3000', '  ')
    if line_feed:
        text = text.replace('\r\n', u'\n').replace(
            '\n', u'\n').replace('\r', u'\n')
    else:
        text = text.replace('\r', '').replace('\n', '')
    if delete_space:
        text = text.replace(' ', '').strip()
    else:
        text = text.strip()
    text = text.replace(',', '，')
    for i in deletions:
        text = text.replace(i, '')
    return text

async def fortuneTelling(
        ln: str,
        fn: str,
        sex: int,
        date: datetime,
        bt: str = ''
):
    """
    说明：
        八字算命(来源 http://www.dajiazhao.com/sm )
        字典数据说明：
        - info str		基本信息
        - name str		姓名
        - birthday
            - gc str    公历生日
            - lc str    农历生日
        - wxsx str      五行属相
        - bz list       八字
        - wx list       五行
        - ny list       纳音
        - bzwxgs list   八字五行个数, [金, 木, 水, 火, 土]
        - sjys str      四季用神参考
        - qtbjdhys str  穷通宝鉴调候用神参考
        - rgxx str      日干心性
        - rgzcs str     日干支层次
        - rgzfx str     日干支分析
        - wxskzhyj str  五行生克制化宜忌
        - wxzx str      五行之性
        - szwxskxb str  四柱五行生克中对应需补的脏腑和部位
        - syfw str      宜从事行业与方位
        - sxgx str      生肖个性
        - smth str      三命通会
        - yrsml         月日时命理
            - y list    月 |
            - r list    日 | => [标题, 文本]
            - s list    时 |

    参数：
        :param ln: Lastname 姓，汉字
        :param fn: Firstname 名，汉字
        :param sex: 性别，[int]: 1.男, 2.女
        :param date: 出生日期，精确到分钟
        :param bt: 血型，[A, B, O, AB, ]
    """
    if not is_all_zh(ln):
        raise ValueError('ln must be a string.')
    if len(ln) > 2 or len(ln) <= 0:
        raise ValueError('1 <= len(ln) <= 2')
    if not is_all_zh(fn):
        raise ValueError('fn must be a string.')
    if isinstance(sex, int):
        if sex not in [1, 2]:
            raise ValueError('sex must be 1 or 2')
    else:
        raise TypeError('sex must be a int')
    async with aiohttp.ClientSession() as c:
        r = await c.post(
            'http://www.dajiazhao.com/sm/scbz.asp',
            data=f'''xing={ln}&ming={fn
			}&xingbie={('男' if (sex == 1) else '女')
			}&xuexing={bt
			}&nian={date.year}&yue={date.month}&ri={date.day
			}&hh={date.hour}&mm={date.minute}'''.encode('gb2312'),
            headers=headers
        )
        soup = BeautifulSoup((await r.text('gb2312')), features="lxml")
    if len(soup.select('.ttop2 dl dd font')) == 0:
        # 判定无结果
        raise RuntimeError('Unable to get data.')
    # 开始分析处理
    result = {
        'info': '',		# 基本信息
        'name': '',		# 姓名
        'birthday':
        {
            'gc': '',   # 公历生日
            'lc': ''    # 农历生日
        },
        'wxsx': '',		# 五行属相
        'bz': [],		# 八字
        'wx': [],		# 五行
        'ny': [],       # 纳音
        'bzwxgs': [],   # 八字五行个数, [金, 木, 水, 火, 土]
        'sjys': '',     # 四季用神参考
        'qtbjdhys': '',  # 穷通宝鉴调候用神参考
        'rgxx': '',     # 日干心性
        'rgzcs': '',    # 日干支层次
        'rgzfx': '',    # 日干支分析
        'wxskzhyj': '',  # 五行生克制化宜忌
        'wxzx': '',     # 五行之性
        'szwxskxb': '',  # 四柱五行生克中对应需补的脏腑和部位
        'syfw': '',     # 宜从事行业与方位
        'sxgx': '',     # 生肖个性
        'smth': '',     # 三命通会
        'yrsml': {      # 月日时命理
            'y': [],    # 月    \
            'r': [],    # 日    | => [标题, 文本]
            's': []     # 时    /
        },
    }
    # region main
    # 获得当前算命者信息
    ttopp2 = soup.select_one('.ttop2 dl dd')
    result['info'] = processing_text(ttopp2.text)
    # 分析表格
    tables = soup.select('table tbody')
    # table1
    t1 = tables[0]
    trs = t1.select('tr')
    tr1 = trs[0]
    # 名字
    result['name'] = processing_text(
        tr1.select('td')[0].text, delete_space=True
    )
    # 公历生日
    gc = tr1.select('td:nth-child(n+4):not(:last-child)')
    for i in gc:
        result['birthday']['gc'] += i.text
    # 五行属相
    tfes = tr1.select_one('td:last-child').text.split('重要说明')[0]
    result['wxsx'] = processing_text(tfes, delete_space=True)
    tr2 = trs[1]
    # 农历生日
    gc = tr2.select('td:nth-child(n+2)')
    for i in gc:
        result['birthday']['lc'] += i.text
    tr3 = trs[2]
    # 八字
    for i in tr3.select('td')[1:]:
        result['bz'].append(i.text.strip())
    tr4 = trs[3]
    # 五行
    for i in tr4.select('td')[1:]:
        result['wx'].append(i.text.strip())
    tr5 = trs[4]
    # 纳音
    for i in tr5.select('td')[1:]:
        result['ny'].append(i.text.strip())
    # 八字五行个数
    ecfln = processing_text(tables[1].select_one('tr td').text, ['八字五行个数 : '])
    # 正则开始匹配
    for i in ['金', '木', '水', '火', '土']:
        result['bzwxgs'].append(int(re.search(f'(\d+)个{i}', ecfln).group(1)))
    # 四季用神参考
    result['sjys'] = processing_text(
        tables[2].select_one('tr:first-child td').text, ['四季用神参考 : '], delete_space=True
    )
    # 穷通宝鉴调候用神参考
    result['qtbjdhys'] = processing_text(
        tables[2].select_one('tr:last-child td').text, ['穷通宝鉴调候用神参考 : '], delete_space=True
    )
    # 日干心性
    result['rgxx'] = processing_text(
        tables[3].select_one('tr td:last-child').text, delete_space=True
    )
    # 日干支层次
    result['rgzcs'] = processing_text(
        tables[4].select_one('tr td:last-child').text, delete_space=True
    )
    # 日干支分析
    tables[5].select_one('tr td:last-child font').decompose()
    result['rgzfx'] = processing_text(
        tables[5].select_one('tr td:last-child').text
    )
    trs = tables[6].select('tr')
    # 五行生克制化宜忌
    result['wxskzhyj'] = processing_text(
        trs[0].select_one('td:last-child').text, delete_space=True, line_feed=True
    )
    # 五行之性
    result['wxzx'] = processing_text(
        trs[1].select_one('td:last-child').text, delete_space=True
    )
    # 四柱五行生克中对应需补的脏腑和部位
    result['szwxskxb'] = processing_text(
        trs[2].select_one('td:last-child').text, delete_space=True
    )
    # 宜从事行业与方位
    result['syfw'] = processing_text(
        trs[3].select_one('td:last-child').text, delete_space=True
    )
    # 生肖个性
    sxgx = tables[7].select_one('tr td:last-child')
    # url = sxgx.select_one('script').get('src')
    # async with aiohttp.ClientSession() as c:
    #     r = await c.get('http://www.dajiazhao.com/'+url, headers=headers)
    #     t = re.search('<p>(.+)<a', (await r.text())).group(1)
    em = sxgx.select_one('em')
    emt = em.text
    em.decompose()
    result['sxgx'] = processing_text(
        f'''
        {sxgx.text}

        {emt}
        ''', delete_space=True, line_feed=True
    )
    # 三命通会
    result['smth'] = processing_text(
        tables[8].select_one('tr td:last-child').text, delete_space=True, line_feed=True
    )
    # 月日时命理
    trs = tables[9].select('tr')
    y = trs[0].select('td')
    result['yrsml']['y'].append(y[1].text)
    result['yrsml']['y'].append(
        processing_text(y[2].text, delete_space=True, line_feed=True)
    )
    r = trs[1].select('td')
    result['yrsml']['r'].append(r[0].text)
    result['yrsml']['r'].append(
        processing_text(r[1].text, delete_space=True, line_feed=True)
    )
    s = trs[2].select('td')
    result['yrsml']['s'].append(s[0].text)
    result['yrsml']['s'].append(
        processing_text(s[1].text, delete_space=True, line_feed=True)
    )
    # endregion
    return result

def linefeed(string, length):
    return re.sub(
        '(.{'+str(length)+'}[，。？！]?)',
        (lambda i: i.group(0)+'\n'),
        string
    )

TESTWIDTH = 45

replies = {
    'group': {
        'beginning': [
            text('乐意至极，但您真的要在这大庭广众之下做这种事情？')
            + face(0)
            + text('万一算出什么不好的东西怎么办...')
            + face(13),

        ],
        'cancel': [
            text('好吧好吧，如果你还是想算，可以悄悄的来找我哦')
            + face(20) + face(20)
        ]
    },
    'start':[
        '开始了！如果你中间不想算了，可以随时告诉我'
    ],
    'not understand': [
        face(32)
        + text('您在说什么呐，我怎么听不懂呢？')
    ],
    'ln': [
        '您贵姓？',
    ],
    'wrong ln': [
        '请认真一点，这明显就不是一个姓氏！',
        '请不要在这件事上开玩笑！'
    ],
    'fn': [
        '您的名字是什么？不要包括姓氏'
    ],
    'wrong fn': [
        '请认真一点，这明显就不是您的名！',
        '请不要在这件事上开玩笑！'
    ],
    'sex': [
        '您的性别是？'
    ],
    'wrong sex': [
        '不要开玩笑了！您到底是男是女？'
    ],
    'birthday': [
        '请问您是哪一天出生的？公历哦'
    ],
    'wrong birthday': [
        '我无法理解您的生日，请再说一次'
    ],
    'btime': [
        '请问您是{:%Y-%m-%d}几点几分出生的？可以只精确到小时'
    ],
    'wrong btime': [
        '您...这时间不太对啊，请认真一点！'
    ],
    'bt': [
        '好，下一个。您的血型是什么，如果不知道的话请跟我说「不知道」'
    ],
    'wrong bt': [
        '您这，有点不对啊！我所知道的血型只有 A, B, O, AB 四种，您是哪一种？'
    ],
    'confirm': [
        '''请确认您的数据：
姓：「{}」
名：「{}」
性别：「{}」
生日：「{:%Y-%m-%d %H:%M}」
血型：「{}」'''
    ],
    'cancel': [
        '好吧，您可真无聊...那不弄了'
    ],
    'getting': [
        '正在帮您进行八字算命...'
    ],
}
msg_false = ['不', '否']
msg_true = ['确定', '当然', '没错', '没关系', '可以', '是']
msg_cancel = ['取消', '算了', '不弄了']

def has(text, words: list):
    for i in words:
        if i in text:
            return True
    return False

@ft.handle()
async def _(bot: Bot, event: MessageEvent, state: T_State):
    if isinstance(event, GroupMessageEvent):
        await bot.send(
            event, random.choice(replies['group']['beginning'])
        )
    elif isinstance(event, PrivateMessageEvent):
        state['allow'] = True
        await bot.send(event, random.choice(replies['start']))
        await asyncio.sleep(1)
        await bot.send(event, random.choice(replies['ln']))

@ft.got('allow')
async def _(bot: Bot, event: GroupMessageEvent, state: T_State):
    if has(event.raw_message, msg_false) or has(event.raw_message, msg_cancel):
        await ft.finish(random.choice(replies['group']['cancel']))
    elif has(event.raw_message, msg_true):
        state['allow'] = True
        await bot.send(event, random.choice(replies['start']))
        await asyncio.sleep(1)
        await bot.send(event, random.choice(replies['ln']))
    else:
        state['allow'] = None
        await ft.reject(random.choice(replies['not understand']))

@ft.got('ln')
async def _(bot: Bot, event: MessageEvent, state: T_State):
    if has(event.raw_message, msg_cancel):
        await ft.finish(random.choice(replies['cancel']))
    ln = state['ln']
    if not is_all_zh(ln) or 0 == len(ln) or len(ln) > 2:
        await ft.reject(random.choice(replies['wrong ln']))
    else:
        await bot.send(event, random.choice(replies['fn']))

@ft.got('fn')
async def _(bot: Bot, event: MessageEvent, state: T_State):
    if has(event.raw_message, msg_cancel):
        await ft.finish(random.choice(replies['cancel']))
    fn = state['fn']
    if not is_all_zh(fn) or 0 == len(fn) or len(fn) > 3:
        await ft.reject(random.choice())
    else:
        await bot.send(event, random.choice(replies['sex']))

@ft.got('sex')
async def _(bot: Bot, event: MessageEvent, state: T_State):
    if has(event.raw_message, msg_cancel):
        await ft.finish(random.choice(replies['cancel']))
    sex = state['sex']
    if sex == '男':
        state['sex'] = 1
    elif sex == '女':
        state['sex'] = 2
    else:
        await ft.reject(random.choice(replies['wrong sex']))
        return
    await bot.send(event, random.choice(replies['birthday']))

@ft.got('birthday')
async def _(bot: Bot, event: MessageEvent, state: T_State):
    if has(event.raw_message, msg_cancel):
        await ft.finish(random.choice(replies['cancel']))
    birthday = state['birthday']
    rb = re.match('(\d{4})[-./年](\d{1,2})[-./月](\d{1,2})', birthday)
    if rb is None:
        await ft.reject(random.choice(replies['wrong birthday']))
    else:
        state['year'] = int(rb.group(1))
        state['month'] = int(rb.group(2))
        state['day'] = int(rb.group(3))
    await bot.send(
        event, random.choice(
            replies['btime']
        ).format(
            datetime.datetime(state['year'], state['month'], state['day'])
        )
    )

@ft.got('btime')
async def _(bot: Bot, event: MessageEvent, state: T_State):
    if has(event.raw_message, msg_cancel):
        await ft.finish(random.choice(replies['cancel']))
    btime = state['btime']
    rbt = re.match('(\d{1,2})[点时:](\d{0,2})', btime)
    if rbt is None:
        await ft.reject(random.choice(replies['wrong btime']))
    else:
        state['hour'] = int(rbt.group(1))
        try:
            state['minute'] = int(rbt.group(2))
        except:
            state['minute'] = 0
    await bot.send(event, random.choice(replies['bt']))

@ft.got('bt')
async def _(bot: Bot, event: MessageEvent, state: T_State):
    if has(event.raw_message, msg_cancel):
        await ft.finish(random.choice(replies['cancel']))
    bt = state['bt']
    if bt == '不知道':
        state['bt'] = ''
    elif bt not in ['A', 'B', 'O', 'AB']:
        await ft.reject(random.choice(replies['wrong bt']))
    await bot.send(
        event,
        text(random.choice(replies['confirm']).format(
            state['ln'],
            state['fn'],
            '男' if(state['sex'] == 1) else '女',
            datetime.datetime(
                state['year'],
                state['month'],
                state['day'],
                state['hour'],
                state['minute']
            ),
            '未知' if(state['bt'] == '') else state['bt']
        ))
    )
    await asyncio.sleep(1)
    await bot.send(event, '如果资料正确，请发送「确定」开始，否则发送「取消」退出')

@ft.got('st')
async def _(bot: Bot, event: MessageEvent, state: T_State):
    if state['st'] == '取消':
        await ft.finish(random.choice(replies['cancel']))
    elif state['st'] == '确定':
        await bot.send(event, random.choice(replies['getting']))
        data = (await fortuneTelling(
            state['ln'],
            state['fn'],
            state['sex'],
            datetime.datetime(
                state['year'],
                state['month'],
                state['day'],
                state['hour'],
                state['minute']
            ),
            state['bt']
        ))
        draw = ImgDraw(bg)
        await draw.init()
        draw.pos = (30, 30)
        await draw.openfont(font)
        #
        await draw.putText(data['name'], 0, 30, fontsize=48, fill=JIANJINGYUHONG)
        await draw.putText('出生\n时间', 1, 15, fontsize=24, fill=CAOMOLIHONG)
        await draw.putText(
            f"公历：{data['birthday']['gc']}\n农历：{data['birthday']['lc']}",
            0, 30, fontsize=24
        )
        draw.x = 30
        # await draw.putText('基本信息', 0, 10, fontsize=36)
        # await draw.putText(data['info'], 0, 30, fontsize=24)

        await draw.putText('五行属相', 0, 5, fontsize=30)
        await draw.putText(data['wxsx'], 0, 15, fontsize=24)

        await draw.putText('''八字：\n五行：\n纳音：''', 1, 10, fontsize=24)
        await draw.putText(f'''{data['bz'][0]}\n{data['wx'][0]}\n{data['ny'][0]}''', 1, 10, fontsize=24)
        await draw.putText(f'''{data['bz'][1]}\n{data['wx'][1]}\n{data['ny'][1]}''', 1, 10, fontsize=24)
        await draw.putText(f'''{data['bz'][2]}\n{data['wx'][2]}\n{data['ny'][2]}''', 1, 10, fontsize=24)
        await draw.putText(f'''{data['bz'][3]}\n{data['wx'][3]}\n{data['ny'][3]}''', 0, 30, fontsize=24)
        draw.x = 30
        await draw.putText(
            f'''八字五行个数：{data['bzwxgs'][0]}个金，{data['bzwxgs'][1]}个木，{
                data['bzwxgs'][2]}个水，{data['bzwxgs'][3]}个火，{data['bzwxgs'][4]}个土。''',
            0, 15, fontsize=24
        )
        await draw.putText('四季用神参考', 0, 10, fontsize=36)
        await draw.putText(linefeed(data['sjys'], TESTWIDTH), 0, 30, fontsize=24)
        await draw.putText('穷通宝鉴调候用神参考', 0, 10, fontsize=36)
        await draw.putText(linefeed(data['qtbjdhys'], TESTWIDTH), 0, 30, fontsize=24)
        await draw.putText('日干心性', 0, 10, fontsize=36)
        await draw.putText(linefeed(data['rgxx'], TESTWIDTH), 0, 30, fontsize=24)
        await draw.putText('日干支层次', 0, 10, fontsize=36)
        await draw.putText(linefeed(data['rgzcs'], TESTWIDTH), 0, 30, fontsize=24)
        await draw.putText('日干支分析', 0, 10, fontsize=36)
        await draw.putText(linefeed(data['rgzfx'], TESTWIDTH), 0, 30, fontsize=24)
        await draw.putText('五行生克制化宜忌', 0, 10, fontsize=36)
        await draw.putText(linefeed(data['wxskzhyj'], TESTWIDTH), 0, 30, fontsize=24)
        await draw.putText('五行之性', 0, 10, fontsize=36)
        await draw.putText(linefeed(data['wxzx'], TESTWIDTH), 0, 30, fontsize=24)
        await draw.putText('四柱五行生克中对应需补的脏腑和部位', 0, 10, fontsize=36)
        await draw.putText(linefeed(data['szwxskxb'], TESTWIDTH), 0, 30, fontsize=24)
        await draw.putText('宜从事行业与方位', 0, 10, fontsize=36)
        await draw.putText(linefeed(data['syfw'], TESTWIDTH), 0, 30, fontsize=24)
        await draw.putText('生肖个性', 0, 10, fontsize=36)
        await draw.putText(linefeed(data['sxgx'], TESTWIDTH), 0, 50, fontsize=24)
        await draw.putText('三命通会', 0, 10, fontsize=36)
        await draw.putText(linefeed(data['smth'], TESTWIDTH), 0, 30, fontsize=24)
        await draw.putText('月日时命理', 0, 10, fontsize=36)
        draw.x += 15
        await draw.putText(data['yrsml']['y'][0], 0, 10, fontsize=28)
        await draw.putText(linefeed(data['yrsml']['y'][1], TESTWIDTH), 0, 30, fontsize=24)
        await draw.putText(data['yrsml']['r'][0], 0, 10, fontsize=28)
        await draw.putText(linefeed(data['yrsml']['r'][1], TESTWIDTH), 0, 30, fontsize=24)
        await draw.putText(data['yrsml']['s'][0], 0, 10, fontsize=28)
        await draw.putText(linefeed(data['yrsml']['s'][1], TESTWIDTH), 0, 30, fontsize=24)

        draw.y += 50
        await draw.putText('此图片乃临时格式，正式格式正在设计...', 0, 5, fill=LUHUI)
        await draw.putText('By Hanjin in Sakuyark@2021', 0, 5, fill=LUHUI)
        await draw.putText('From www.dajiazhao.com', 0, 5, fill=LUHUI)
        out_path = os.path.join(
            '.', 'res', 'ft', 'cards',
            datetime.datetime.now().__format__('%Y%m%d%H%M%S') +
            str(random.randint(10, 99))+'.jpg'
        )
        await draw.save(out_path)
        await bot.send(event, image(out_path), at_sender=True)
        os.remove(out_path)
    else:
        await ft.reject('指令发送有误！')


import torch
from torch import nn
from fusionlab.segmentation.base import SegmentationModel
from fusionlab.utils import autopad
from fusionlab.layers import ConvND, BatchNorm, MaxPool, Upsample

# ref: https://github.com/4uiiurz1/pytorch-nested-unet

class UNet2plus(SegmentationModel):
    def __init__(self, cin, num_cls, base_dim, spatial_dims=2):
        super().__init__()
        self.num_cls = num_cls
        self.encoder = Encoder(cin, base_dim, spatial_dims)
        self.bridger = Bridger()
        self.decoder = Decoder(base_dim, spatial_dims)
        self.head = Head(base_dim, num_cls, spatial_dims)

class BasicBlock(nn.Sequential):
    def __init__(self, cin, cout, spatial_dims=2):
        conv1 = nn.Sequential(
            ConvND(spatial_dims, cin, cout, 3, 1, autopad(3)),
            BatchNorm(spatial_dims, cout),
            nn.ReLU(),
        )
        conv2 = nn.Sequential(
            ConvND(spatial_dims, cout, cout, 3, 1, autopad(3)),
            BatchNorm(spatial_dims, cout),
            nn.ReLU(),
        )
        super().__init__(conv1, conv2)

class Encoder(nn.Module):
    def __init__(self, cin, base_dim, spatial_dims=2):
        """
        UNet Encoder
        Args:
            cin (int): input channels
            base_dim (int): 1st stage dim of conv output
        """
        super().__init__()
        self.pool = MaxPool(spatial_dims, 2, 2)
        self.conv0_0 = BasicBlock(cin, base_dim, spatial_dims)
        self.conv1_0 = BasicBlock(base_dim, base_dim * 2, spatial_dims)
        self.conv2_0 = BasicBlock(base_dim * 2, base_dim * 4, spatial_dims)
        self.conv3_0 = BasicBlock(base_dim * 4, base_dim * 8, spatial_dims)
        self.conv4_0 = BasicBlock(base_dim * 8, base_dim * 16, spatial_dims)

    def forward(self, x):
        x0_0 = self.conv0_0(x)
        x1_0 = self.conv1_0(self.pool(x0_0))
        x2_0 = self.conv2_0(self.pool(x1_0))
        x3_0 = self.conv3_0(self.pool(x2_0))
        x4_0 = self.conv4_0(self.pool(x3_0))
        return [x0_0, x1_0, x2_0, x3_0, x4_0]

class Bridger(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, x):
        return [nn.Identity()(i) for i in x]

class Decoder(nn.Module):
    def __init__(self, base_dim, spatial_dims=2):
        super().__init__()
        dims = [base_dim*(2**i) for i in range(5)]  # [base_dim, base_dim*2, base_dim*4, base_dim*8, base_dim*16]
        self.conv0_1 = BasicBlock(dims[0] + dims[1], dims[0], spatial_dims)
        self.conv1_1 = BasicBlock(dims[1] + dims[2], dims[1], spatial_dims)
        self.conv2_1 = BasicBlock(dims[2] + dims[3], dims[2], spatial_dims)
        self.conv3_1 = BasicBlock(dims[3] + dims[4], dims[3], spatial_dims)

        self.conv0_2 = BasicBlock(dims[0] * 2 + dims[1], dims[0], spatial_dims)
        self.conv1_2 = BasicBlock(dims[1] * 2 + dims[2], dims[1], spatial_dims)
        self.conv2_2 = BasicBlock(dims[2] * 2 + dims[3], dims[2], spatial_dims)

        self.conv0_3 = BasicBlock(dims[0] * 3 + dims[1], dims[0], spatial_dims)
        self.conv1_3 = BasicBlock(dims[1] * 3 + dims[2], dims[1], spatial_dims)

        self.conv0_4 = BasicBlock(dims[0] * 4 + dims[1], dims[0], spatial_dims)
        self.up = Upsample(spatial_dims, scale_factor=2)

    def forward(self, x):
        x0_0, x1_0, x2_0, x3_0, x4_0 = x

        x0_1 = self.conv0_1(torch.cat([x0_0, self.up(x1_0)], 1))
        x1_1 = self.conv1_1(torch.cat([x1_0, self.up(x2_0)], 1))
        x0_2 = self.conv0_2(torch.cat([x0_0, x0_1, self.up(x1_1)], 1))

        x2_1 = self.conv2_1(torch.cat([x2_0, self.up(x3_0)], 1))
        x1_2 = self.conv1_2(torch.cat([x1_0, x1_1, self.up(x2_1)], 1))
        x0_3 = self.conv0_3(torch.cat([x0_0, x0_1, x0_2, self.up(x1_2)], 1))

        x3_1 = self.conv3_1(torch.cat([x3_0, self.up(x4_0)], 1))
        x2_2 = self.conv2_2(torch.cat([x2_0, x2_1, self.up(x3_1)], 1))
        x1_3 = self.conv1_3(torch.cat([x1_0, x1_1, x1_2, self.up(x2_2)], 1))
        x0_4 = self.conv0_4(torch.cat([x0_0, x0_1, x0_2, x0_3, self.up(x1_3)], 1))

        return x0_4

class Head(nn.Sequential):
    def __init__(self, cin, cout, spatial_dims=2):
        """
        Basic Identity
        :param int cin: input channel
        :param int cout: output channel
        """
        conv = ConvND(spatial_dims, cin, cout, 1)
        super().__init__(conv)

if __name__ == '__main__':
    H = W = 224
    dim = 32
    inputs = torch.normal(0, 1, (1, 3, H, W))

    encoder = Encoder(3, base_dim=dim)
    outputs = encoder(inputs)
    for i, o in enumerate(outputs):
        assert list(o.shape) == [1, dim * (2 ** i), H // (2 ** i), W // (2 ** i)]

    bridger = Bridger()
    outputs = bridger(outputs)
    for i, o in enumerate(outputs):
        assert list(o.shape) == [1, dim * (2 ** i), H // (2 ** i), W // (2 ** i)]

    features = [torch.normal(0, 1, (1, dim * (2 ** i), H // (2 ** i), W // (2 ** i))) for i in range(5)]
    decoder = Decoder(dim)
    outputs = decoder(features)
    assert list(outputs.shape) == [1, dim, H, W]

    head = Head(dim, 10)
    outputs = head(outputs)
    assert list(outputs.shape) == [1, 10, H, W]

    unet = UNet2plus(3, 10, dim)
    outputs = unet(inputs)
    assert list(outputs.shape) == [1, 10, H, W]

    print("1D UNet++")
    L = 128
    dim = 32
    inputs = torch.rand(1, 3, L)
    unet = UNet2plus(3, 10, dim, spatial_dims=1)

    outputs = unet(inputs)
    assert list(outputs.shape) == [1, 10, L]

    print("3D UNet++")
    D = H = W = 32
    dim = 32
    inputs = torch.rand(1, 3, D, H, W)
    unet = UNet2plus(3, 10, dim, spatial_dims=3)

    outputs = unet(inputs)
    assert list(outputs.shape) == [1, 10, D, H, W]


# 获取数据
from utils import load_data,accuracy,load_graph
from self_attention import Co_attention
import torch
import torch.optim as optim
import torch.nn.functional as F

import time
import argparse
import numpy as np

from config import Config

# Training settings
parser = argparse.ArgumentParser()
parser.add_argument('--no-cuda', action='store_true', default=False,
                    help='Disables CUDA training.')

parser.add_argument('--fastmode', action='store_true', default=False,
                    help='Validate during training pass.')

parser.add_argument('--seed', type=int, default=42, help='Random seed.')

parser.add_argument('--epochs', type=int, default=200,
                    help='Number of epochs to train.')

parser.add_argument('--lr', type=float, default=0.002,
                    help='Initial learning rate.')

# default = 5e-4
parser.add_argument('--weight_decay', type=float, default=10e-4,
                    help='Weight decay (L2 loss on parameters).')

parser.add_argument('--hidden', type=int, default=16,
                    help='Number of hidden units.')

parser.add_argument('--dropout', type=float, default=0.5,
                    help='Dropout rate (1 - keep probability).')

parser.add_argument("-d", "--dataset", help="dataset", type=str, default="uai")
parser.add_argument("-l", "--labelrate", help="labeled data for train per class", type = int, default=60)

# args = parser.parse_args()
args, unknown = parser.parse_known_args()

config_file = "./config/" + str(args.labelrate) + str(args.dataset) + ".ini"
config = Config(config_file)

args.cuda = not args.no_cuda and torch.cuda.is_available()

np.random.seed(args.seed)
torch.manual_seed(args.seed)
if args.cuda:
    torch.cuda.manual_seed(args.seed)

# Load data
# 导入数据
# adj, features, labels, idx_train, idx_val, idx_test = load_data()

# 把数据变成[batch,n,feature]
# features = torch.unsqueeze(features,dim=1)

# 获取图结构
# sadj, fadj = load_graph(args.labelrate, config)
# feature_edges = np.genfromtxt("./data/coraml/test20.txt", dtype=np.int32)
# print(feature_edges)
sadj, fadj = load_graph(args.labelrate, config)
features, labels, idx_train, idx_test = load_data(config)

# Model and optimizer
model = Co_attention(num_attention_heads = 1,
                      input_size = features.shape[-1],
                      hidden_size1 = 300,
                      hidden_size2 = 150,
                      hidden_dropout_prob = 0,
                      class_size = labels.max().item() + 1)

# 优化器
optimizer = optim.Adam(model.parameters(),
                       lr=args.lr, weight_decay=args.weight_decay)

if args.cuda:
    model.cuda()
    features = features.cuda()
    # adj = adj.cuda()
    labels = labels.cuda()
    idx_train = idx_train.cuda()
    # idx_val = idx_val.cuda()
    idx_test = idx_test.cuda()
    sadj = sadj.cuda()
    fadj = fadj.cuda()

def train(epoch):
    t = time.time()
    model.train()
    optimizer.zero_grad()
    output = model(features,sadj=sadj,fadj=fadj)

    # 每次拿140个数据训练
    loss_train = F.nll_loss(output[idx_train], labels[idx_train])
    acc_train = accuracy(output[idx_train], labels[idx_train])
    loss_train.backward()
    optimizer.step()

    if not args.fastmode:
        # Evaluate validation set performance separately,
        # deactivates dropout during validation run.
        model.eval()
        output = model(features,sadj=sadj,fadj=fadj)
        # output = output.view(output.shape[0], -1)

    # loss_val = F.nll_loss(output[idx_val], labels[idx_val])
    # acc_val = accuracy(output[idx_val], labels[idx_val])
    # print('Epoch: {:04d}'.format(epoch+1),
    #       'loss_train: {:.4f}'.format(loss_train.item()),
    #       'acc_train: {:.4f}'.format(acc_train.item()),
    #       'loss_val: {:.4f}'.format(loss_val.item()),
    #       'acc_val: {:.4f}'.format(acc_val.item()),
    #       'time: {:.4f}s'.format(time.time() - t))
    print('Epoch: {:04d}'.format(epoch + 1),
          'loss_train: {:.4f}'.format(loss_train.item()),
          'acc_train: {:.4f}'.format(acc_train.item()),
          'time: {:.4f}s'.format(time.time() - t))

def test():
    model.eval()
    output = model(features,sadj=sadj,fadj=fadj)
    output = output.view(output.shape[0], -1)
    loss_test = F.nll_loss(output[idx_test], labels[idx_test])
    acc_test = accuracy(output[idx_test], labels[idx_test])
    print("Test set results:",
          "loss= {:.4f}".format(loss_test.item()),
          "accuracy= {:.4f}".format(acc_test.item()))

# Train model
# 训练了200次
t_total = time.time()
max_acc = 0
loss = 100
max_epoch = 0
for epoch in range(args.epochs):
    train(epoch)

    model.eval()
    output = model(features, sadj=sadj, fadj=fadj)
    output = output.view(output.shape[0], -1)
    loss_test = F.nll_loss(output[idx_test], labels[idx_test])
    acc_test = accuracy(output[idx_test], labels[idx_test])

    if acc_test >= max_acc:
        max_acc = acc_test
        loss = loss_test
        max_epoch = epoch

print("Test set results:",
        "loss= {:.4f}".format(loss.item()),
        "max_acc= {:.4f}".format(max_acc.item()),
         "max_epoch = {}".format(max_epoch))

print("Optimization Finished!")
print("Total time elapsed: {:.4f}s".format(time.time() - t_total))

# Testing
test()


import dataclasses
import math

from typing import Optional, Sequence
from contrib import event_codec

import note_seq
import t5.data

DECODED_EOS_ID = -1
DECODED_INVALID_ID = -2

# defaults for vocabulary config
DEFAULT_STEPS_PER_SECOND = 100
DEFAULT_MAX_SHIFT_SECONDS = 10
DEFAULT_NUM_VELOCITY_BINS = 127

@dataclasses.dataclass
class VocabularyConfig:
    """Vocabulary configuration parameters."""
    steps_per_second: int = DEFAULT_STEPS_PER_SECOND
    max_shift_seconds: int = DEFAULT_MAX_SHIFT_SECONDS
    num_velocity_bins: int = DEFAULT_NUM_VELOCITY_BINS

    @property
    def abbrev_str(self):
        s = ''
        if self.steps_per_second != DEFAULT_STEPS_PER_SECOND:
            s += 'ss%d' % self.steps_per_second
        if self.max_shift_seconds != DEFAULT_MAX_SHIFT_SECONDS:
            s += 'ms%d' % self.max_shift_seconds
        if self.num_velocity_bins != DEFAULT_NUM_VELOCITY_BINS:
            s += 'vb%d' % self.num_velocity_bins
        return s

def num_velocity_bins_from_codec(codec: event_codec.Codec):
    """Get number of velocity bins from event codec."""
    lo, hi = codec.event_type_range('velocity')
    return hi - lo

def velocity_to_bin(velocity, num_velocity_bins):
    if velocity == 0:
        return 0
    else:
        return math.ceil(num_velocity_bins * velocity / note_seq.MAX_MIDI_VELOCITY)

def bin_to_velocity(velocity_bin, num_velocity_bins):
    if velocity_bin == 0:
        return 0
    else:
        return int(note_seq.MAX_MIDI_VELOCITY * velocity_bin / num_velocity_bins)

def drop_programs(tokens, codec: event_codec.Codec):
    """Drops program change events from a token sequence."""
    min_program_id, max_program_id = codec.event_type_range('program')
    return tokens[(tokens < min_program_id) | (tokens > max_program_id)]

def build_codec(vocab_config: VocabularyConfig):
    """Build event codec."""
    event_ranges = [
        event_codec.EventRange('pitch', note_seq.MIN_MIDI_PITCH,
                               note_seq.MAX_MIDI_PITCH),
        # velocity bin 0 is used for note-off
        event_codec.EventRange('velocity', 0, vocab_config.num_velocity_bins),
        # used to indicate that a pitch is present at the beginning of a segment
        # (only has an "off" event as when using ties all pitch events until the
        # "tie" event belong to the tie section)
        event_codec.EventRange('tie', 0, 0),
        event_codec.EventRange('program', note_seq.MIN_MIDI_PROGRAM,
                               note_seq.MAX_MIDI_PROGRAM),
        event_codec.EventRange('drum', note_seq.MIN_MIDI_PITCH,
                               note_seq.MAX_MIDI_PITCH),
    ]

    return event_codec.Codec(
        max_shift_steps=(vocab_config.steps_per_second *
                         vocab_config.max_shift_seconds),
        steps_per_second=vocab_config.steps_per_second,
        event_ranges=event_ranges)

def vocabulary_from_codec(codec: event_codec.Codec):
    return GenericTokenVocabulary(codec.num_classes, extra_ids=t5.data.DEFAULT_EXTRA_IDS)

class GenericTokenVocabulary():
    """Vocabulary with pass-through encoding of tokens."""

    def __init__(self, regular_ids: int, extra_ids: int = 0):
        # The special tokens: 0=PAD, 1=EOS, and 2=UNK
        self._num_special_tokens = 3
        self._num_regular_tokens = regular_ids
        self.extra_ids = extra_ids
        super().__init__()

    @property
    def eos_id(self) -> Optional[int]:
        return 1

    @property
    def unk_id(self) -> Optional[int]:
        return 2

    @property
    def _base_vocab_size(self) -> int:
        """Number of ids.

        Returns:
          an integer, the vocabulary size
        """
        return self._num_special_tokens + self._num_regular_tokens

    def encode(self, token_ids: Sequence[int]) -> Sequence[int]:
        """Encode a list of tokens ids as a list of integers.

        To keep the first few ids for special tokens, increase ids by the number
        of special tokens.

        Args:
          token_ids: array of token ids.

        Returns:
          a list of integers (not terminated by EOS)
        """
        encoded = []
        for token_id in token_ids:
            if not 0 <= token_id < self._num_regular_tokens:
                raise ValueError(
                    f'token_id {token_id} does not fall within valid range of '
                    f'[0, {self._num_regular_tokens})')
            encoded.append(token_id + self._num_special_tokens)

        return encoded

    def decode(self, ids: Sequence[int]) -> Sequence[int]:
        """Decode a list of integers to a list of token ids.

        The special tokens of PAD and UNK as well as extra_ids will be
        replaced with DECODED_INVALID_ID in the output. If EOS is present, it will
        be the final token in the decoded output and will be represented by
        DECODED_EOS_ID.

        Args:
          ids: a list of integers

        Returns:
          a list of token ids.
        """
        # convert all the extra ids  to INVALID_ID
        def _decode_id(encoded_id):
            if encoded_id == self.eos_id:
                return DECODED_EOS_ID
            elif encoded_id < self._num_special_tokens:
                return DECODED_INVALID_ID
            elif encoded_id >= self._base_vocab_size:
                return DECODED_INVALID_ID
            else:
                return encoded_id - self._num_special_tokens
        ids = [_decode_id(i) for i in ids]
        return ids

    def num_special_tokens(self):
        return self._num_special_tokens

    def __eq__(self, other):
        their_extra_ids = other.extra_ids
        their_num_regular_tokens = other._num_regular_tokens
        return (self.extra_ids == their_extra_ids and
                self._num_regular_tokens == their_num_regular_tokens)

def num_embeddings(vocabulary: GenericTokenVocabulary) -> int:
    """Vocabulary size as a multiple of 128 for TPU efficiency."""
    return 128 * math.ceil(vocabulary.vocab_size / 128)


from itertools import count

import torch
import torch.nn as nn
import torch.optim as optim
import numpy as np
import torch.autograd as autograd

import random
import time
import sys
from collections import deque
from tqdm import tqdm

from model.sdf_net import SDFNet
from model.progressive_gan import Discriminator, LATENT_CODE_SIZE, RESOLUTIONS
from util import create_text_slice, device, standard_normal_distribution, get_voxel_coordinates

SDF_CLIPPING = 0.1
from util import create_text_slice
from datasets import VoxelDataset
from torch.utils.data import DataLoader

def get_parameter(name, default):
    for arg in sys.argv:
        if arg.startswith(name + '='):
            return arg[len(name) + 1:]
    return default

ITERATION = int(get_parameter('iteration', 3))
# Continue with model parameters that were previously trained at the SAME iteration
# Otherwise, it will use the model parameters of the previous iteration or initialize randomly at iteration 0
CONTINUE = "continue" in sys.argv

FADE_IN_EPOCHS = 10
BATCH_SIZE = 16
GRADIENT_PENALTY_WEIGHT = 10
NUMBER_OF_EPOCHS = int(get_parameter('epochs', 250))

VOXEL_RESOLUTION = RESOLUTIONS[ITERATION]
print(VOXEL_RESOLUTION)
dataset = VoxelDataset.from_split('../data/chairs/voxels_{:d}/{{:s}}.npy'.format(VOXEL_RESOLUTION),
                                  '../data/chairs/test.txt')
data_loader = DataLoader(dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=4)

def get_generator_filename(iteration):
    return 'hybrid_progressive_gan_generator_{:d}.to'.format(iteration)

generator = SDFNet(device='cpu')
generator.filename = get_generator_filename(ITERATION)
generator.load()

if torch.cuda.device_count() > 1:
    print("Using dataparallel with {:d} GPUs.".format(torch.cuda.device_count()))
    generator_parallel = nn.DataParallel(generator)
else:
    generator_parallel = generator

generator_parallel.to(device)

LOG_FILE_NAME = "plots/hybrid_gan_training_{:d}.csv".format(ITERATION)
first_epoch = 0
if 'continue' in sys.argv:
    log_file_contents = open(LOG_FILE_NAME, 'r').readlines()
    first_epoch = len(log_file_contents)

log_file = open(LOG_FILE_NAME, "a" if "continue" in sys.argv else "w")

generator_optimizer = optim.RMSprop(generator_parallel.parameters(), lr=0.0001)

show_viewer = "nogui" not in sys.argv

if show_viewer:
    from rendering import MeshRenderer

    viewer = MeshRenderer()

def sample_latent_codes(current_batch_size):
    latent_codes = standard_normal_distribution.sample(sample_shape=[current_batch_size, LATENT_CODE_SIZE]).to(device)
    latent_codes = latent_codes.repeat((1, 1, grid_points.shape[0])).reshape(-1, LATENT_CODE_SIZE)
    return latent_codes

grid_points = get_voxel_coordinates(VOXEL_RESOLUTION, return_torch_tensor=True)
grid_points_default_batch = grid_points.repeat((BATCH_SIZE, 1))

def test():
    progress = tqdm(total=NUMBER_OF_EPOCHS * (len(dataset) // BATCH_SIZE + 1),
                    initial=first_epoch * (len(dataset) // BATCH_SIZE + 1))

    for valid_sample in data_loader:
        try:

            valid_sample = valid_sample.to(device)
            current_batch_size = valid_sample.shape[0]
            if current_batch_size == BATCH_SIZE:
                batch_grid_points = grid_points_default_batch
            else:
                batch_grid_points = grid_points.repeat((current_batch_size, 1))

            generator_optimizer.zero_grad()

            latent_codes = sample_latent_codes(current_batch_size)
            fake_sample = generator_parallel(batch_grid_points, latent_codes)
            fake_sample = fake_sample.reshape(-1, VOXEL_RESOLUTION, VOXEL_RESOLUTION, VOXEL_RESOLUTION)
            if batch_index % 50 == 0 and show_viewer:
                viewer.set_voxels(fake_sample[0, :, :, :].squeeze().detach().cpu().numpy())
            if batch_index % 50 == 0 and "show_slice" in sys.argv:
                tqdm.write(create_text_slice(fake_sample[0, :, :, :] / SDF_CLIPPING))

            generator_optimizer.step()

            progress.update()
        except KeyboardInterrupt:
            if show_viewer:
                viewer.stop()
            return

test()
log_file.close()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# This file is part of Viper - https://github.com/viper-framework/viper
# See the file 'LICENSE' for copying permission.

import os
from setuptools import setup

from viper.common.version import __version__

__description__ = "Binary Analysis & Management Framework"

def get_packages(package):
    """
    Return root package and all sub-packages.
    """
    return [dirpath
            for dirpath, dirnames, filenames in os.walk(package)
            if os.path.exists(os.path.join(dirpath, "__init__.py"))]

def get_package_data(package):
    """
    Return all files under the root package, that are not in a
    package themselves.
    """
    walk = [(dirpath.replace(package + os.sep, "", 1), filenames)
            for dirpath, dirnames, filenames in os.walk(package)
            if not os.path.exists(os.path.join(dirpath, "__init__.py"))]

    filepaths = []
    for base, filenames in walk:
        filepaths.extend([os.path.join(base, filename)
                          for filename in filenames
                          if not filename.endswith('pyc')])
    return {package: filepaths}

setup(
    name="viper-framework",
    version=__version__,
    author="Claudio Guarnieri",
    author_email="nex@nex.sx",
    description=__description__,
    long_description=__description__,
    url="http://viper.li",
    platforms="any",
    entry_points={
        "console_scripts": [
            "viper = viper.core.ui.main:main",
        ],
    },
    packages=get_packages("viper"),
    package_data=get_package_data("viper"),
    include_package_data=True,
    install_requires=[
        "python-magic==0.4.18",
        "requests[socks]==2.24.0",
        "requests-cache==0.5.2",
        "scandir==1.10",
        "six==1.15.0",
        "sqlalchemy==1.3.13",
        "terminaltables==3.1.0",
        "pydeep==0.4",
        "rarfile==3.1",
    ],
    zip_safe=False,
    tests_require=["pytest"],
    # BSD 3-Clause License:
    # - http://choosealicense.com/licenses/bsd-3-clause
    # - http://opensource.org/licenses/BSD-3-Clause
    license="BSD 3-Clause",
    # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
    classifiers=[
        "Topic :: Security",
        "License :: OSI Approved :: BSD License",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3.4",
        "Programming Language :: Python :: 3.5",
        "Programming Language :: Python :: 3.6",
        "Programming Language :: Python :: 3.7",
        "Operating System :: POSIX :: Linux",
    ],
    keywords="binary analysis management malware research",
)


import argparse
import csv
import os
import sys

import torch
from pytorch_pretrained_bert.file_utils import PYTORCH_PRETRAINED_BERT_CACHE
from pytorch_pretrained_bert.modeling import BertForSequenceClassification
from pytorch_pretrained_bert.optimization import BertAdam
from pytorch_pretrained_bert.tokenization import BertTokenizer
from torch.utils.data import TensorDataset

project_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
sys.path.append(project_path)
from src import scaling
from src.training import *

class InputExample(object):
    """A single training/test example for simple sequence classification."""
    def __init__(self, guid, text_a, text_b=None, label=None):
        """Constructs a InputExample.

		Args:
			guid: Unique id for the example.
			text_a: string. The untokenized text of the first sequence. For single
			sequence tasks, only this sequence must be specified.
			text_b: (Optional) string. The untokenized text of the second sequence.
			Only must be specified for sequence pair tasks.
			label: (Optional) string. The label of the example. This should be
			specified for train and dev examples, but not for test examples.
		"""
        self.guid = guid
        self.text_a = text_a
        self.text_b = text_b
        self.label = label

class InputFeatures(object):
    """A single set of features of data."""
    def __init__(self, input_ids, input_mask, segment_ids, label_id):
        self.input_ids = input_ids
        self.input_mask = input_mask
        self.segment_ids = segment_ids
        self.label_id = label_id

class DataProcessor(object):
    """Base class for data converters for sequence classification data sets."""
    def get_train_examples(self, data_dir):
        """Gets a collection of `InputExample`s for the train set."""
        raise NotImplementedError()

    def get_dev_examples(self, data_dir):
        """Gets a collection of `InputExample`s for the dev set."""
        raise NotImplementedError()

    def get_labels(self):
        """Gets the list of labels for this data set."""
        raise NotImplementedError()

    @classmethod
    def _read_tsv(cls, input_file, quotechar=None):
        """Reads a tab separated value file."""
        with open(input_file, "r", encoding='utf-8') as f:
            reader = csv.reader(f, delimiter="\t", quotechar=quotechar)
            lines = []
            for line in reader:
                lines.append(line)
            return lines

class MrpcProcessor(DataProcessor):
    """Processor for the MRPC data set (GLUE version)."""
    def get_train_examples(self, data_dir):
        """See base class."""
        # logger.info("LOOKING AT {}".format(os.path.join(data_dir, "train.tsv")))
        return self._create_examples(
            self._read_tsv(os.path.join(data_dir, "train.tsv")), "train")

    def get_dev_examples(self, data_dir):
        """See base class."""
        return self._create_examples(
            self._read_tsv(os.path.join(data_dir, "dev.tsv")), "dev")

    def get_labels(self):
        """See base class."""
        return ["0", "1"]

    def _create_examples(self, lines, set_type):
        """Creates examples for the training and dev sets."""
        examples = []
        for (i, line) in enumerate(lines):
            if i == 0:
                continue
            guid = "%s-%s" % (set_type, i)
            text_a = line[3]
            text_b = line[4]
            label = line[0]
            examples.append(
                InputExample(guid=guid,
                             text_a=text_a,
                             text_b=text_b,
                             label=label))
        return examples

class Sst2Processor(DataProcessor):
    """Processor for the SST-2 data set (GLUE version)."""
    def get_train_examples(self, data_dir):
        """See base class."""
        return self._create_examples(
            self._read_tsv(os.path.join(data_dir, "train.tsv")), "train")

    def get_dev_examples(self, data_dir):
        """See base class."""
        return self._create_examples(
            self._read_tsv(os.path.join(data_dir, "dev.tsv")), "dev")

    def get_labels(self):
        """See base class."""
        return ["0", "1"]

    def _create_examples(self, lines, set_type):
        """Creates examples for the training and dev sets."""
        examples = []
        for (i, line) in enumerate(lines):
            if i == 0:
                continue
            guid = "%s-%s" % (set_type, i)
            text_a = line[0]
            label = line[1]
            examples.append(
                InputExample(guid=guid,
                             text_a=text_a,
                             text_b=None,
                             label=label))
        return examples

class ColaProcessor(DataProcessor):
    """Processor for the CoLA data set (GLUE version)."""
    def get_train_examples(self, data_dir):
        """See base class."""
        return self._create_examples(
            self._read_tsv(os.path.join(data_dir, "train.tsv")), "train")

    def get_dev_examples(self, data_dir):
        """See base class."""
        return self._create_examples(
            self._read_tsv(os.path.join(data_dir, "dev.tsv")), "dev")

    def get_labels(self):
        """See base class."""
        return ["0", "1"]

    def _create_examples(self, lines, set_type):
        """Creates examples for the training and dev sets."""
        examples = []
        for (i, line) in enumerate(lines):
            guid = "%s-%s" % (set_type, i)
            text_a = line[3]
            label = line[1]
            examples.append(
                InputExample(guid=guid,
                             text_a=text_a,
                             text_b=None,
                             label=label))
        return examples

def convert_examples_to_features(examples, label_list, max_seq_length,
                                 tokenizer):
    """Loads a data file into a list of `InputBatch`s."""

    label_map = {label: i for i, label in enumerate(label_list)}

    features = []
    for (ex_index, example) in enumerate(examples):
        tokens_a = tokenizer.tokenize(example.text_a)

        tokens_b = None
        if example.text_b:
            tokens_b = tokenizer.tokenize(example.text_b)
            # Modifies `tokens_a` and `tokens_b` in place so that the total
            # length is less than the specified length.
            # Account for [CLS], [SEP], [SEP] with "- 3"
            _truncate_seq_pair(tokens_a, tokens_b, max_seq_length - 3)
        else:
            # Account for [CLS] and [SEP] with "- 2"
            if len(tokens_a) > max_seq_length - 2:
                tokens_a = tokens_a[:(max_seq_length - 2)]

        # The convention in BERT is:
        # (a) For sequence pairs:
        #  tokens:   [CLS] is this jack ##son ##ville ? [SEP] no it is not . [SEP]
        #  type_ids: 0   0  0    0    0     0       0 0    1  1  1  1   1 1
        # (b) For single sequences:
        #  tokens:   [CLS] the dog is hairy . [SEP]
        #  type_ids: 0   0   0   0  0     0 0
        #
        # Where "type_ids" are used to indicate whether this is the first
        # sequence or the second sequence. The embedding vectors for `type=0` and
        # `type=1` were learned during pre-training and are added to the wordpiece
        # embedding vector (and position vector). This is not *strictly* necessary
        # since the [SEP] token unambigiously separates the sequences, but it makes
        # it easier for the model to learn the concept of sequences.
        #
        # For classification tasks, the first vector (corresponding to [CLS]) is
        # used as as the "sentence vector". Note that this only makes sense because
        # the entire model is fine-tuned.
        tokens = ["[CLS]"] + tokens_a + ["[SEP]"]
        segment_ids = [0] * len(tokens)

        if tokens_b:
            tokens += tokens_b + ["[SEP]"]
            segment_ids += [1] * (len(tokens_b) + 1)

        input_ids = tokenizer.convert_tokens_to_ids(tokens)

        # The mask has 1 for real tokens and 0 for padding tokens. Only real
        # tokens are attended to.
        input_mask = [1] * len(input_ids)

        # Zero-pad up to the sequence length.
        padding = [0] * (max_seq_length - len(input_ids))
        input_ids += padding
        input_mask += padding
        segment_ids += padding

        assert len(input_ids) == max_seq_length
        assert len(input_mask) == max_seq_length
        assert len(segment_ids) == max_seq_length

        label_id = label_map[example.label]
        # if ex_index < 5:
        # 	logger.info("*** Example ***")
        # 	logger.info("guid: %s" % (example.guid))
        # 	logger.info("tokens: %s" % " ".join(
        # 			[str(x) for x in tokens]))
        # 	logger.info("input_ids: %s" % " ".join([str(x) for x in input_ids]))
        # 	logger.info("input_mask: %s" % " ".join([str(x) for x in input_mask]))
        # 	logger.info(
        # 			"segment_ids: %s" % " ".join([str(x) for x in segment_ids]))
        # 	logger.info("label: %s (id = %d)" % (example.label, label_id))

        features.append(
            InputFeatures(input_ids=input_ids,
                          input_mask=input_mask,
                          segment_ids=segment_ids,
                          label_id=label_id))
    return features

def _truncate_seq_pair(tokens_a, tokens_b, max_length):
    """Truncates a sequence pair in place to the maximum length."""

    # This is a simple heuristic which will always truncate the longer sequence
    # one token at a time. This makes more sense than truncating an equal percent
    # of tokens from each, since if one sequence is very short then each token
    # that's truncated likely contains more information than a longer sequence.
    while True:
        total_length = len(tokens_a) + len(tokens_b)
        if total_length <= max_length:
            break
        if len(tokens_a) > len(tokens_b):
            tokens_a.pop()
        else:
            tokens_b.pop()

def get_args():
    parser = argparse.ArgumentParser()
    parser.add_argument('--lr',
                        default=0.0005,
                        type=float,
                        help='learning rate')
    parser.add_argument('--scale', action='store_true')
    parser.add_argument('--resume',
                        '-r',
                        action='store_true',
                        help='resume from checkpoint')
    parser.add_argument('--data_dir', type=str)
    parser.add_argument('--epoch_size', type=int)
    parser.add_argument('--batch_size', type=int, default=32)
    parser.add_argument(
        '--model',
        type=str,
        help=
        'bert-base-uncased/bert-large-uncased/bert-base-cased/bert-large-cased/'
        'bert-base-multilingual-uncased/bert-base-multilingual-cased')
    parser.add_argument('--model_dir', type=str)
    parser.add_argument('--task_name', type=str, help='cola/sst2/mrpc')
    parser.add_argument('--max_seq_length', type=int, default=128)
    parser.add_argument('--target', type=float)
    parser.add_argument('--num_epochs', type=int)
    parser.add_argument('--patience', type=int)
    parser.add_argument('--manager_addr', type=str, default='localhost')
    parser.add_argument('--manager_port', type=int, default=17834)
    parser.add_argument('--job_id', type=int)
    parser.add_argument('--port', type=int)
    parser.add_argument('--local_rank', type=int, default=0)
    return parser.parse_args()

ARGS = get_args()

device = 'cuda'
torch.backends.cudnn.benchmark = True

sa = scaling.ScalingAgent(ARGS.job_id, 'nlp', ARGS.local_rank, ARGS.port,
                          ARGS.manager_addr, ARGS.manager_port)

# Data
print('==> Preparing data..')

processors = {
    "cola": ColaProcessor,
    "sst2": Sst2Processor,
    "mrpc": MrpcProcessor,
}

num_labels_task = {
    "cola": 2,
    "sst2": 2,
    "mrpc": 2,
}

task_name = ARGS.task_name.lower()

processor = processors[task_name]()
num_labels = num_labels_task[task_name]
label_list = processor.get_labels()

tokenizer = BertTokenizer.from_pretrained(ARGS.model, do_lower_case=True)

train_examples = processor.get_train_examples(ARGS.data_dir)
train_features = convert_examples_to_features(train_examples, label_list,
                                              ARGS.max_seq_length, tokenizer)
all_input_ids = torch.tensor([f.input_ids for f in train_features],
                             dtype=torch.long)
all_input_mask = torch.tensor([f.input_mask for f in train_features],
                              dtype=torch.long)
all_segment_ids = torch.tensor([f.segment_ids for f in train_features],
                               dtype=torch.long)
all_label_ids = torch.tensor([f.label_id for f in train_features],
                             dtype=torch.long)
trainset = TensorDataset(all_input_ids, all_input_mask, all_segment_ids,
                         all_label_ids)
if ARGS.epoch_size is not None and ARGS.epoch_size < len(trainset):
    trainset = torch.utils.data.Subset(trainset, range(ARGS.epoch_size))

eval_examples = processor.get_dev_examples(ARGS.data_dir)
eval_features = convert_examples_to_features(eval_examples, label_list,
                                             ARGS.max_seq_length, tokenizer)
all_input_ids = torch.tensor([f.input_ids for f in eval_features],
                             dtype=torch.long)
all_input_mask = torch.tensor([f.input_mask for f in eval_features],
                              dtype=torch.long)
all_segment_ids = torch.tensor([f.segment_ids for f in eval_features],
                               dtype=torch.long)
all_label_ids = torch.tensor([f.label_id for f in eval_features],
                             dtype=torch.long)
testset = TensorDataset(all_input_ids, all_input_mask, all_segment_ids,
                        all_label_ids)

print('==> Loaded %d training samples, %d test samples' %
      (len(trainset), len(testset)))

# Model
print('==> Building model: ' + ARGS.model)
net = BertForSequenceClassification.from_pretrained(
    ARGS.model,
    # cache_dir=PYTORCH_PRETRAINED_BERT_CACHE / 'distributed_{}'.format(ARGS.local_rank),
    num_labels=num_labels)

start_epoch = 0  # start from epoch 0 or last checkpoint epoch

if ARGS.resume:
    # Load checkpoint.
    print('==> Resuming from checkpoint..')
    assert os.path.isdir(
        ARGS.model_dir), 'Error: no checkpoint directory found!'
    checkpoint = torch.load(ARGS.model_dir + '/ckpt.t7')
    net.load_state_dict(checkpoint['net'])
    start_epoch = checkpoint['epoch']

net = net.to(device)

param_optimizer = list(net.named_parameters())
no_decay = ['bias', 'LayerNorm.bias', 'LayerNorm.weight']
optimizer_grouped_parameters = [{
    'params':
    [p for n, p in param_optimizer if not any(nd in n for nd in no_decay)],
    'weight_decay':
    0.01
}, {
    'params':
    [p for n, p in param_optimizer if any(nd in n for nd in no_decay)],
    'weight_decay':
    0.0
}]
optimizer = BertAdam(optimizer_grouped_parameters, lr=ARGS.lr)
criterion = torch.nn.CrossEntropyLoss()

sa.load(net=net,
        criterion=criterion,
        optimizer=optimizer,
        trainset=trainset,
        testset=testset,
        batch_size=ARGS.batch_size,
        lr=ARGS.lr,
        num_labels=num_labels,
        start_epoch=start_epoch,
        scale=True if ARGS.scale else False)

if ARGS.resume:
    sa.adjust_learning_rate(checkpoint['lr'])

epoch = train(sa, patience=ARGS.patience)
save(sa, epoch, ARGS.model_dir)


import json
from dataclasses import dataclass, asdict
from typing import Optional

from spark_pipeline_framework.progress_logger.progress_logger import ProgressLogger
from spark_pipeline_framework.utilities.api_helper.http_request import (
    HelixHttpRequest,
    RequestType,
)

@dataclass
class OAuth2Credentails:
    client_id: str
    client_secret: str
    grant_type: Optional[str] = "client_credentials"
    audience: Optional[str] = None

class OAuth2ClientCredentialsFlow:
    def __init__(
        self,
        *,
        auth_url: str,
        auth_credentails: OAuth2Credentails,
        progress_logger: Optional[ProgressLogger],
    ) -> None:
        """
        Encapsulate the logic to connect to OAuth2 servers using client credentials flow

        :param auth_url: OAuth2 token url
        :param auth_credentails: OAuth2 credentails like client id, secrets, etc
        :param progress_logger: Progress logger
        """
        assert auth_url
        self.auth_url: str = auth_url
        self.auth_credentails = auth_credentails
        self.progress_logger: Optional[ProgressLogger] = progress_logger

    def get_token(self) -> Optional[str]:
        http_request = HelixHttpRequest(
            url=self.auth_url,
            payload=asdict(
                self.auth_credentails,
                dict_factory=lambda x: {k: v for (k, v) in x if v is not None},
            ),
            request_type=RequestType.POST,
        )

        response = http_request.get_result()
        if self.progress_logger:
            self.progress_logger.write_to_log(
                f"Received from {self.auth_url}: {json.dumps(response.result)}"
            )
        token = response.result.get("access_token")

        return token


print("Initiating... please wait.\n")

import requests
import csv
import re
import random
import time
import pandas as pd
from sys import exit
from bs4 import BeautifulSoup

# ===== DEFINE FUNCTIONS =====

search_from, URL_edit = "", ""

def wait():
    print("Waiting for a few secs...")
    time.sleep(random.randrange(1, 6))
    print("Waiting done. Continuing...\n")

def checkPage():
    global search_from
    if "scholar.google.com" in URL_input:
        search_from = "Google Scholar"
        print("Input is from: Google Scholar.\n")
    elif "pubmed" in URL_input:
        search_from = "Pubmed"
        print("Input is from: PubMed.\n")
    elif "sciencedirect.com" in URL_input:
        search_from = "Science Direct"
        print("Input is from: Science Direct.\n")
    elif "plos.org" in URL_input:
        search_from = "PLOS"
        print("Input is from: PLOS.\n")

    else:
        print("Page URL undefined.\n")

# ===== GETTING AND SETTING THE URL =====

URL_input = input("Please paste search URL and press Enter:")
URL_ori = URL_input
headers = requests.utils.default_headers()
headers.update(
    {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36",
    }
)
checkPage()

# ===== MAIN FRAMEWORK =====

try:

    # SETTING UP THE CSV FILE

    outfile = open("scrapped_science_direct.csv", "w", newline="", encoding="utf-8")
    writer = csv.writer(outfile)
    df = pd.DataFrame(
        columns=["Title", "Article Rype", "Year", "Source", "Authors", "Link"]
    )

    # SETTING & GETTING PAGE NUMBER

    page_num = 0
    offset = 0
    page_view = 100
    URL_edit = str(URL_ori + "&show=" + str(page_view) + "&offset=" + str(offset))

    page = requests.get(URL_edit, headers=headers, timeout=None)
    soup = BeautifulSoup(page.content, "html.parser")
    wait()

    search_results = soup.find_all("span", class_="search-body-results-text").text
    print(search_results)

    if "About" in search_results:
        search_results_split = search_results.split("results")[0].split("About")[1]
    elif "results" in search_results:
        search_results_split = search_results.split("results")[0]
    else:
        seascrapped_science_directrch_results_split = search_results.split("result")[0]

    search_results_num = int("".join(filter(str.isdigit, search_results_split)))
    page_total_num = int(search_results_num / 10) + 1
    print(f"Total page number: {page_total_num}")
    print(f"Total search results: {search_results_num}.\n")

except AttributeError:

    print("Opss! ReCaptcha is probably preventing the code from running.")
    print("Please consider running in another time.\n")
    # exit()
    wait()

wait()

# # EXTRACTING INFORMATION

for i in range(page_total_num):

    # SETTING UP URL SECOND TIME

    page_num_up = page_num + i
    print(f"Going to page {page_num_up}.\n")
    URL_edit = str(URL_ori + "&show=" + str(page_view) + "&offset=" + str(page_num_up))
    wait()
    # if page_num_up != 2 and page_num_up != 1:
    # 	# time.sleep(2)
    headers = requests.utils.default_headers()
    headers.update(
        {
            "User-Agent": "Mozilla/15.0 (X11; Ubuntu; Linux x86_64; rv:52.0) Gecko/20210916 Firefox/95.0",
        }
    )

    page = requests.get(URL_edit, headers=headers, timeout=None)
    soup = BeautifulSoup(page.content, "html.parser")
    wait()
    response = requests.get(URL_edit, headers=headers)

    # check successful response
    if response.status_code != 200:
        print("Status code:", response.status_code)
        raise Exception("Failed to fetch web page ")

    results = soup.find("div", id="srp-results-list")
    paper_doc = BeautifulSoup(response.text, "html.parser")

    # EXTRACTING INFORMATION

    try:

        job_elements = results.find_all("div", class_="result-item-content")
        for job_element in job_elements:
            try:
                article_type = job_element.find(
                    "span", class_="article-type u-clr-grey8"
                ).text
                article_title = job_element.find("span", class_="anchor-text").text
                article_src = job_element.find(
                    "span", class_="srctitle-date-fields"
                ).text
                article_authors = job_element.find(
                    "ol", class_="Authors hor reduce-list"
                ).text
                article_date = article_src.split(",")[-2]
                source = article_src.split(",")[:-1]
                links = job_element.find(
                    "a", class_="anchor download-link anchor-default"
                )
                link_url = links["href"]

            except Exception as e:
                print(e)
                continue
            print(article_title)

            df2 = pd.DataFrame(
                [
                    [
                        article_title,
                        article_type,
                        article_date,
                        source,
                        article_authors,
                        link_url,
                    ]
                ],
                columns=[
                    "Title",
                    "Cites",
                    "Year",
                    "Reference",
                    "Publisher",
                    "Tag",
                    "Link",
                    "Description",
                ],
            )
            df = pd.concat([df, df2], ignore_index=True)
            headers = ["Title", "Article Rype", "Year", "Source", "Authors", "Link"]

            with open(
                "scrapped_science_direct.csv", "a", newline="", encoding="utf-8"
            ) as f:
                writer = csv.writer(f)
                writer.writerow(
                    [
                        article_title,
                        article_type,
                        article_date,
                        source,
                        article_authors,
                        link_url,
                    ]
                )

            # time.sleep(1)
    except AttributeError:
        print("Opss! ReCaptcha is probably preventing the code from running.")
        print("Please consider running in another time.\n")
        # exit()
        wait()

df.index += 1
df.to_csv("scrapped_gscholar.csv", encoding="utf-8")
outfile.close()

# ===== CODE FOR SCIENCE  =====

# END OF PROGRAM

print("Job finished, Godspeed you! Cite us.")


import json

from django.utils import timezone
from datetime import datetime, timedelta
from pprint import pprint
import uuid
import names
from random import randint

sellPoints = []
dropOffs = []
cups = []
users = []

def abstract_traffic():
    with open('../../../dataset/passagierfrequenz.json') as json_data:
        d = json.load(json_data)
        global total_stations
        total_stations = []

        reduction = 0.01
        last_travelers = 200
        min_cups = 20
        for row in d:
            res = {}
            try:
                station = row['fields']['bahnhof_haltestelle']
                travelers = row['fields']['dtv']
                [lat, lon] = row['fields']['geopos']

            except KeyError:  # includes simplejson.decoder.JSONDecodeError
                travelers = -1
            if travelers != -1:
                if travelers * reduction < 10:
                    res['name'] = str(station)
                    res['cups'] = min_cups
                else:
                    res['name'] = str(station)
                    res['cups'] = int(travelers * reduction)

                last_travelers = travelers
            else:
                if last_travelers * reduction < 10:
                    res['name'] = str(station)
                    res['cups'] = min_cups
                else:
                    res['name'] = str(station)
                    res['cups'] = int(travelers * reduction)
            res['lat'] = lat
            res['lon'] = lon
            # print(lat, lon)
            total_stations.append(res)

        # print(total_stations)

def make_cups():
    data_out = []
    k = 0
    for i, station in enumerate(total_stations):
        total_cups = total_stations[i]['cups']
        for j in range(total_cups):
            if j < total_stations[i]['cups2']:
                cup = {'model': 'website.Cup',
                       "pk": str(uuid.uuid4()),
                       'fields': {'sellPoint': i}
                       }
            else:
                cup = {'model': 'website.Cup',
                       "pk": str(uuid.uuid4()),
                       'fields': {'dropOff': i}
                       }
            data_out.append(cup)
            list.append(cups, cup)
            k += 1

    with open('../../../dataset/data_cups.json', 'w') as outfile:
        json.dump(data_out, outfile, sort_keys=False, ensure_ascii=False)

def make_data_results():
    data_out = []

    company = {'fields': {}}
    company['pk'] = 0
    company['model'] = 'website.Company'

    company['fields']['name'] = 'company0'

    data_out.append(company)

    for i in range(0, len(total_stations)):
        station = {'fields': {}}
        station['pk'] = i
        station['model'] = 'website.Station'

        station['fields']['name'] = total_stations[i]['name']
        station['fields']['lat'] = total_stations[i]['lat']
        station['fields']['lon'] = total_stations[i]['lon']

        cups = total_stations[i]['cups']
        total_stations[i]['cups2'] = int(0.75*cups*(randint(8, 10)/10))
        cups2 = total_stations[i]['cups2']
        if cups >= 693:
            imp = 5
        elif cups >= 40:
            imp = 4
        elif cups >= 20:
            imp = 3
        elif cups >= 10:
            imp = 2
        else:
            imp = 1
        station['fields']['importance'] = imp

        data_out.append(station)

        sellPoint = {'fields': {}}
        sellPoint['pk'] = i
        sellPoint['model'] = 'website.SellPoint'

        name = 'sellpoint' + str(i)
        sellPoint['fields']['name'] = name
        sellPoint['fields']['company'] = 0
        sellPoint['fields']['station'] = i
        sellPoint['fields']['cups_desired'] = cups
        sellPoint['fields']['cups_current'] = cups2
        data_out.append(sellPoint)

        list.append(sellPoints, i)

        name = names.get_first_name()
        surname = names.get_last_name()
        username = name.lower() + "." + surname.lower() + "." + str(randint(1, 2019))
        email = username + "@shop.ch"
        user = {'model': 'website.CustomUser',
                'fields': {"username": username, 'role': 1, "first_name": name, "last_name": surname, "email": email, "sellPoint": sellPoint["pk"]}
                }
        data_out.append(user)

        dropOff = {'fields': {}}
        dropOff['pk'] = i
        dropOff['model'] = 'website.DropOff'

        dropOff['fields']['station'] = i
        data_out.append(dropOff)

        list.append(dropOffs, i)

    with open('../../../dataset/data_results.json', 'w') as outfile:
        json.dump(data_out, outfile, sort_keys=False, ensure_ascii=False)

def make_users():
    data_out = []
    k = 0
    for i, station in enumerate(total_stations):
        total_cups = total_stations[i]['cups']
        for j in range(int(0.1*(total_cups))):
            name = names.get_first_name()
            surname = names.get_last_name()
            username = name.lower() + "." + surname.lower() + "." + str(randint(1, 2019))
            email = username + "@sbb.ch"
            user = {'model': 'website.CustomUser',
                    "pk": k,
                   'fields': {"username": username, 'role': 1, "first_name": name, "last_name": surname, "email": email}
                   }
            data_out.append(user)

            list.append(users, user)

            k += 1

    with open('../../../dataset/data_users.json', 'w') as outfile:
        json.dump(data_out, outfile, sort_keys=False, ensure_ascii=False)

def make_history():
    data_out = []
    current = datetime.now()-timedelta(hours=1)
    shifts = [50, 25, 0, 0, 50, 150, 400, 750, 1500, 650, 575, 675, 850, 525, 425, 575, 675, 425, 325, 275, 225, 200, 150, 75]
    for _ in range(24*7):
        shift = current.hour
        currentshift = randint(int(shifts[shift]/2), shifts[shift])
        for i in range(currentshift):
            cup = cups[randint(0, len(cups) - 1)]
            time1 = (current-timedelta(minutes=randint(0, 60)))
            time1_str = time1.replace(tzinfo=timezone.utc).astimezone(tz=None).strftime("%Y-%m-%d %H:%M:%S")
            dropoff = dropOffs[randint(0, len(dropOffs) - 1)]
            time4 = (time1-timedelta(hours=randint(2, 4), minutes=randint(0, 60)))
            time4_str = time4.replace(tzinfo=timezone.utc).astimezone(tz=None).strftime("%Y-%m-%d %H:%M:%S")
            user = users[randint(0, len(users) - 1)]["pk"]
            time3 = (time4-timedelta(hours=randint(0, 1), minutes=randint(0, 60)))
            time3_str = time3.replace(tzinfo=timezone.utc).astimezone(tz=None).strftime("%Y-%m-%d %H:%M:%S")
            sellpoint = sellPoints[randint(0, len(sellPoints) - 1)]
            time2 = (time3-timedelta(hours=randint(0, 1), minutes=randint(0, 60)))
            time2_str = time2.replace(tzinfo=timezone.utc).astimezone(tz=None).strftime("%Y-%m-%d %H:%M:%S")
            history = {'model': 'website.History',
                       'fields': {"time1": time1_str, "time2": time2_str, "time3": time3_str, "time4": time4_str,
                                  "sellPoint": sellpoint, "dropOff": dropoff, "user": user, "cup": cup["pk"]}}
            cup["sellPoint"] = sellpoint
            data_out.append(history)
        current -= timedelta(hours=1)

    with open('../../../dataset/data_history.json', 'w') as outfile:
        json.dump(data_out, outfile, sort_keys=False, ensure_ascii=False)

def main():
    abstract_traffic()
    print("Traffic abstracted!")
    make_data_results()
    print("Date results done!")
    make_cups()
    print("Cups done!")
    make_users()
    print("Users done!")
    make_history()
    print("History done!")

if __name__ == '__main__':
    main()


# 2019 Emir Erbasan (humanova)
# MIT License, see LICENSE for more details

import os
import discord
from discord.ext import commands
import codecs
from utils import confparser, default, permissions, eval

class Owner(commands.Cog):

    def __init__(self, bot):
        self.bot = bot
        self.config = confparser.get("config.json")

    @commands.command()
    @commands.bot_has_permissions(manage_messages=True)
    @commands.check(permissions.is_owner)
    async def say(self, ctx, *, message : str):
        try:
            await ctx.message.delete()
            await ctx.send(message)
        except:
            pass

    @commands.command()
    @commands.check(permissions.is_owner)
    async def load(self, ctx, name: str):
        try:
            self.bot.load_extension(f"cogs.{name}")
        except Exception as e:
            return await ctx.send(default.traceback_maker(e))
        await ctx.send(f"Loaded extension **{name}.py**")

    @commands.command()
    @commands.check(permissions.is_owner)
    async def unload(self, ctx, name: str):
        try:
            self.bot.unload_extension(f"cogs.{name}")
        except Exception as e:
            return await ctx.send(default.traceback_maker(e))
        await ctx.send(f"Unloaded extension **{name}.py**")

    @commands.command()
    @commands.check(permissions.is_owner)
    async def reload(self, ctx, name: str):
        try:
            self.bot.reload_extension(f"cogs.{name}")
        except Exception as e:
            return await ctx.send(default.traceback_maker(e))
        await ctx.send(f"Reloaded extension **{name}.py**")

    @commands.command()
    @commands.check(permissions.is_owner)
    async def reloadall(self, ctx):
        error_collection = []
        for file in os.listdir("cogs"):
            if file.endswith(".py"):
                name = file[:-3]
                try:
                    self.bot.reload_extension(f"cogs.{name}")
                except Exception as e:
                    error_collection.append(
                        [file, default.traceback_maker(e, advance=False)]
                    )

        if error_collection:
            output = "\n".join([f"**{g[0]}** ```diff\n- {g[1]}```" for g in error_collection])
            return await ctx.send(output)

        await ctx.send("Successfully reloaded all extensions")

    @commands.command(aliases=['exec', 'eval'])
    @commands.check(permissions.is_owner)
    async def execute(self, ctx, *, cmd: str):
        message = await ctx.send(f"executing {cmd}...")
        output = eval.evaluate_command(cmd)

        await message.edit(content=f"```{output}```")
        await message.add_reaction("👍")

    @commands.command()
    @commands.check(permissions.is_owner)
    async def servers(self, ctx):
        server_list = ""
        for guild in self.bot.guilds:
            server_list += f"{guild.member_count} :: {guild.name}\n"
        await ctx.send(f"```{server_list}```")

    @commands.command()
    @commands.check(permissions.is_owner)
    async def dump_users(self, ctx):
        file = codecs.open(self.config.users_log_path, "w+", "utf-8")

        for g in self.bot.guilds:
            #print(f"Logging server : {g.name}")
            file.write(f"==== {g.name} -- {g.member_count} users\n")
            for mem in g.members:
                file.write(f"{str(mem)}\n")
        file.close()

        await ctx.send(file=discord.File(fp=self.config.users_log_path, filename="users_dump.txt"))

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


import argparse
import logging
import pandas as pd

from article import Article
from database import Base, engine, Session

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('filename', type=str)

    args = parser.parse_args()
    filename = args.filename

    articles = pd.read_csv(filename, delimiter=';')

    Base.metadata.create_all(engine)
    postgres_session = Session()
    for index, row in articles.iterrows():
        article = Article(
            row['uid'],
            row['body'],
            row['host'],
            row['title'],
            row['newspaper_uid'],
            row['n_tokens_body'],
            row['n_tokens_title'],
            row['url'],
            row['sentiment']
        )
        postgres_session.add(article)

    postgres_session.commit()
    postgres_session.close()

main()


'''将纯文本文件 city.txt为城市信息, 里面的内容写入xlsx'''

import json
import pandas as pd

def open_file_to_dict(filepath):
    with open(filepath,'r',encoding= "utf-8") as f:
        data = f.read()
        dictionary = json.loads(data)  #将文本类型转化为字典
    return dictionary

def change_txt_to_xlsx(content:dict,name):
    dataframe = pd.DataFrame(content.values(),index = content.keys())
    xlsx_file = dataframe.to_excel(name,header = False)
    return xlsx_file

if __name__ =="__main__":
    filepath = "../doc/city.txt"
    content = open_file_to_dict(filepath)
    name = 'city.xlsx'
    change_txt_to_xlsx(content,name)


from torch import nn

class ResNet(nn.Module):

    def __init__(self,
                 num_classes=10,
                 proj_type='linear',
                 num_blocks=[1, 1, 1, 1],
                 c_hidden=[16, 32, 64, 128],
                 init_max_pool=False,
                 **kwargs):
        super().__init__()
        self.num_classes = num_classes
        self.proj_type = proj_type
        self.num_blocks = num_blocks
        self.c_hidden = c_hidden
        self.init_max_pool = init_max_pool
        self._create_network()
        self._init_params()

    def _create_network(self):
        c_hidden = self.c_hidden

        self.input_net = nn.Sequential(
            nn.Conv2d(3, c_hidden[0], kernel_size=3, padding=1, stride=2,
                      bias=False),
            nn.BatchNorm2d(c_hidden[0]),
            nn.ReLU(),
        )
        if self.init_max_pool:
            self.input_net.append(nn.MaxPool2d(kernel_size=3, stride=2, padding=1))

        blocks = []
        for block_idx, block_count in enumerate(self.num_blocks):
            for bc in range(block_count):
                subsample = (bc == 0 and block_idx > 0)
                blocks.append(
                    ResNetBlock(c_in=c_hidden[
                        block_idx if not subsample else (block_idx - 1)],
                                subsample=subsample,
                                c_out=c_hidden[block_idx])
                )
        self.blocks = nn.Sequential(*blocks)
        self.output_net = nn.Sequential(
            nn.AdaptiveAvgPool2d((1, 1)),
            nn.Flatten(),
            nn.Linear(c_hidden[-1], self.num_classes)
        )

    def _init_params(self):
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                nn.init.kaiming_normal_(m.weight, mode='fan_out',
                                        nonlinearity='relu')
            elif isinstance(m, nn.BatchNorm2d):
                nn.init.constant_(m.weight, 1)
                nn.init.constant_(m.bias, 0)

    def forward(self, x):
        x = self.input_net(x)
        x = self.blocks(x)
        x = self.output_net(x)
        return x

class ResNetBlock(nn.Module):

    def __init__(self, c_in, subsample=False, c_out=-1):
        super().__init__()
        if not subsample:
            c_out = c_in

        self.net = nn.Sequential(
            nn.Conv2d(c_in, c_out, kernel_size=3, padding=1,
                      stride=1 if not subsample else 2, bias=False),
            nn.BatchNorm2d(c_out),
            nn.ReLU(),
            nn.Conv2d(c_out, c_out, kernel_size=3, padding=1, bias=False),
            nn.BatchNorm2d(c_out)
        )

        self.downsample = nn.Conv2d(c_in, c_out, kernel_size=1,
                                    stride=2) if subsample else None
        self.act_fn = nn.ReLU()

    def forward(self, x):
        z = self.net(x)
        if self.downsample is not None:
            x = self.downsample(x)
        out = z + x
        out = self.act_fn(out)
        return out


import setuptools

with open('VERSION.txt', 'r') as f:
    version = f.read().strip()

setuptools.setup(
    name="odoo11-addons-oca-connector-ecommerce",
    description="Meta package for oca-connector-ecommerce Odoo addons",
    version=version,
    install_requires=[
        'odoo11-addon-connector_ecommerce',
    ],
    classifiers=[
        'Programming Language :: Python',
        'Framework :: Odoo',
        'Framework :: Odoo :: 11.0',
    ]
)


from flask_wtf import FlaskForm
from wtforms import StringField, SelectField, SelectMultipleField, SubmitField
from wtforms.validators import DataRequired

PRICES = ['$', '$$', '$$$', '$$$$']

TYPES = [
    ( 'bakeries','Bakeries' ),
    ( 'bubbletea','Bubble Tea' ),
    ( 'cocktailbars','Cocktails' ),
    ( 'bars','Bars' ),
    ( 'brazilian','Brazilian' ),
    ( 'coffee','Coffee & Tea' ),
    ( 'chickenshop','Chicken Shop' ),
    ( 'desserts','Desserts' ),
    ( 'donuts','Donuts' ),
    ( 'dimsum','Dim Sum' ),
    ( 'ethiopian','Ethiopian' ),
    ( 'icecream','Ice Cream & Frozen Yogurt' ),
    ( 'juicebars','Juice Bars & Smoothies' ),
    ( 'bbq','Barbeque' ),
    ( 'breakfast_brunch','Breakfast & Brunch' ),
    ( 'burgers','Burgers' ),
    ( 'cafes','Cafes' ),
    ( 'chicken_wings','Chicken Wings' ),
    ( 'chinese','Chinese' ),
    ( 'gluten_free','Gluten-Free' ),
    ( 'german','German' ),
    ( 'gastropubs','Gastropubs' ),
    ( 'french','French' ),
    ( 'hotdogs','Fast Food' ),
    ( 'indpak','Indian' ),
    ( 'latin','Latin' ),
    ( 'italian','Italian' ),
    ( 'japanese','Japanese' ),
    ( 'korean','Korean' ),
    ( 'newamerican','American (New)' ),
    ( 'mediterranean','Mediterranean' ),
    ( 'mexican','Mexican' ),
    ( 'pizza','Pizza' ),
    ( 'ramen','Ramen' ),
    ( 'noodles','Noodles' ),
    ( 'raw_food','Raw Food' ),
    ( 'salad','Salad' ),
    ( 'sandwiches','Sandwiches' ),
    ( 'soulfood','Soul Food' ),
    ( 'soup','Soup' ),
    ( 'seafood','Seafood' ),
    ( 'steak','Steakhouses' ),
    ( 'sushi','Sushi Bars' ),
    ( 'tacos','Tacos' ),
    ( 'tradamerican','American (Traditional)' ),
    ( 'taiwanese','Taiwanese' ),
    ( 'thai','Thai' ),
    ( 'tapasmallplates','Tapas/Small Plates' ),
    ( 'vegetarian','Vegetarian' ),
    ( 'vegan','Vegan' ),
    ( 'vietnamese','Vietnamese' ),
    ('waffles','Waffles' ),
]

TRANSACTIONS = [('delivery','Delivery'), ('pickup','Pick Up'), ('restaurant_reservation','Reservations')]

class AddBusinessForm(FlaskForm):
    name = StringField('Name', validators=[DataRequired()])
    city = StringField('City', validators=[DataRequired()])
    state = StringField('State', validators=[DataRequired()])
    country = StringField('Country', validators=[DataRequired()])
    address = StringField('Address', validators=[DataRequired()])
    zipcode = StringField('Zipcode', validators=[DataRequired()])
    lat = StringField('Latitude')
    lng = StringField('Longitude')
    price_range = SelectField('Price Range', validators=[DataRequired()], choices=PRICES)
    start_time = StringField('Start Time', validators=[DataRequired()])
    end_time = StringField('End Time', validators=[DataRequired()])
    preview_img = StringField('Preview Image URL (optional)')
    phone_number = StringField('Phone Number (optional)')
    types = SelectMultipleField('Categories (select up to 3)', choices=TYPES)
    transactions = SelectMultipleField('Customer Transaction Options', choices=TRANSACTIONS)

    submit = SubmitField('Submit')