import threading
import time
import tkinter
import tkinter as tk
import traceback
from threading import Thread
from tkinter import *
from tkinter import ttk, colorchooser
from tkinter.filedialog import askopenfilename
from tkinter.scrolledtext import ScrolledText
from sqlitedict import SqliteDict
import keyboard as keyboard
import pythoncom
from PIL import Image, ImageTk
from markdown2 import Markdown
from TkHtmlView import TkHtmlView
import sys, os
from pydmdll import DM

class Main_window(object):
    """主窗体"""

    def __init__(self, title, icon, alpha, topmost, bg, width, height, width_adjust, higth_adjust):
        self.root = tk.Tk()
        self.title = title
        self.icon = icon
        self.root.title(title)
        self.root.wm_attributes('-alpha', alpha)
        self.root.wm_attributes('-topmost', topmost)
        self.root.configure(bg=bg)
        self.bg = bg
        self.root.iconbitmap(icon)
        self.width = width
        self.height = height
        self.width_adjust = width_adjust
        self.higth_adjust = higth_adjust

        # 文件执行目录
        self.exe_dir_path = os.path.dirname(os.path.abspath(sys.argv[0]))
        print(self.exe_dir_path)

        self.width, self.height = width, height
        self.root.geometry("%dx%d-%d+%d" % (width, height, width_adjust, higth_adjust))

        self.root.maxsize(width, 2000)
        self.root.minsize(width, 30)

        # 后下手遭殃，可能会被隐藏
        self.frame_bottom = Frame(self.root, bg=bg)
        self.frame_bottom.pack(side=BOTTOM)
        self.frame_top = Frame(self.root, bg=bg)
        self.frame_top.pack(side=TOP)
        self.frame_middle = Frame(self.root, bg=bg)
        self.frame_middle.pack(side=BOTTOM, padx=21, pady=7)

        ttk.Label(self.frame_top, text="轨迹：", background=bg).pack(side=tk.LEFT, pady=3)
        self.comvalue = tkinter.StringVar()
        self.comboxlist = ttk.Combobox(self.frame_top, textvariable=self.comvalue, width=24, state='readonly')
        self.comboxlist.pack(side=tk.LEFT, pady=3)
        self.refresh_photo_image = ImageTk.PhotoImage(
            Image.open(self.exe_dir_path + "/img/" + "refresh.png").resize((18, 18)))
        tk.Button(self.frame_top,
                  command=self.refresh_files,
                  bg=bg,
                  image=self.refresh_photo_image,
                  relief="flat",
                  overrelief="groove").pack(side=tk.LEFT, padx=5, pady=3)

        # 新建按钮
        self.new_image = Image.open(self.exe_dir_path + "/img/" + "24gl-fileEmpty.png").resize((25, 25))
        self.new_photo_image = ImageTk.PhotoImage(self.new_image)
        self.new_button = tk.Button(self.frame_bottom,
                                    command=self.new_track,
                                    bg=bg,
                                    text="编辑", image=self.new_photo_image,
                                    relief="flat",
                                    overrelief="groove")
        self.new_button.pack(side=tk.LEFT, padx=5, pady=3)

        # 编辑按钮
        self.edit_image = Image.open(self.exe_dir_path + "/img/" + "edit.png").resize((25, 25))
        self.edit_photo_image = ImageTk.PhotoImage(self.edit_image)
        self.edit_button = tk.Button(self.frame_bottom,
                                     command=self.edit_track,
                                     bg=bg,
                                     text="编辑",
                                     image=self.edit_photo_image,
                                     relief="flat",
                                     overrelief="groove")
        self.edit_button.pack(side=tk.LEFT, padx=5, pady=3)

        # 开始按钮
        self.start_photo_image = ImageTk.PhotoImage(Image.open(self.exe_dir_path + "/img/" + "开始.png").resize((25, 25)))
        self.start_button = tk.Button(self.frame_bottom,
                                      command=self.start,
                                      bg=bg,
                                      image=self.start_photo_image,
                                      relief="flat",
                                      overrelief="groove")
        self.start_button.pack(side=tk.LEFT, padx=5, pady=3)

        # 透明按钮
        self.alpha_photo_image = ImageTk.PhotoImage(
            Image.open(self.exe_dir_path + "/img/" + "透明度.png").resize((25, 25)))
        self.alpha_button = tk.Button(self.frame_bottom,
                                      command=self.alpha,
                                      bg=bg,
                                      image=self.alpha_photo_image,
                                      relief="flat",
                                      overrelief="groove")
        self.alpha_button.pack(side=tk.LEFT, padx=5, pady=3)

        # 测试按钮
        self.test_photo_image = ImageTk.PhotoImage(
            Image.open(self.exe_dir_path + "/img/" + "shutter.png").resize((25, 25)))
        self.test_button = tk.Button(self.frame_bottom,
                                     command=self.test_track,
                                     bg=bg,
                                     image=self.test_photo_image,
                                     relief="flat",
                                     overrelief="groove")
        self.test_button.pack(side=tk.LEFT, padx=5, pady=3)

        # 帮助按钮
        self.help_photo_image = ImageTk.PhotoImage(
            Image.open(self.exe_dir_path + "/img/" + "帮助.png").resize((25, 25)))
        self.help_button = tk.Button(self.frame_bottom,
                                     command=self.help,
                                     bg=bg,
                                     image=self.help_photo_image,
                                     relief="flat",
                                     overrelief="groove")
        self.help_button.pack(side=tk.LEFT, padx=5, pady=3)

        # 设置按钮
        self.stop_photo_image = ImageTk.PhotoImage(
            Image.open(self.exe_dir_path + "/img/" + "setting.png").resize((25, 25)))
        self.stop_button = tk.Button(self.frame_bottom,
                                     command=self.setting,
                                     bg=bg,
                                     image=self.stop_photo_image,
                                     relief="flat",
                                     overrelief="groove")
        self.stop_button.pack(side=tk.LEFT, padx=5, pady=3)

        # 开启初始化线程
        self.p = Thread(target=self.init)
        self.p.setDaemon(True)
        self.p.start()

        # 注册监听热键
        keyboard.add_hotkey('ctrl+c', self.listen_track_stop)
        keyboard.add_hotkey('ctrl+z', self.close)

        self.root.mainloop()

    def refresh_files(self):
        self.comboxlist.config(values=os.listdir(self.exe_dir_path + "/track/"))
        self.comboxlist.current(0)

    def test_track(self):
        Test_window(height=200, pre_window=self)

    def setting(self):
        Setting_window(height=160, pre_window=self)

    def close(self):
        print("按住了ctrl+z")
        self.root.destroy()

    def init(self):
        time.sleep(1)
        # 耗时UI放到线程里面
        self.wait_window = Wait_window(height=80, pre_window=self)

        # 是否第一次运行
        if not os.path.exists(self.exe_dir_path + "/zod_setting.sqlite"):
            print("第一次运行")
            my_sql_dict = SqliteDict(self.exe_dir_path + '/zod_setting.sqlite')
            my_sql_dict["coordinate"] = [(500, 300)]
            my_sql_dict["mode"] = ["有蜂鸣器声音"]
            my_sql_dict["title"] = ["Honey"]
            my_sql_dict.commit()
            my_sql_dict.close()

        self.my_dict = SqliteDict(self.exe_dir_path + '/zod_setting.sqlite', autocommit=True)

        # 初始化下拉列表
        self.comboxlist.config(values=os.listdir(self.exe_dir_path + "/track/"))
        self.comboxlist.current(0)
        # 初始化大漠插件
        pythoncom.CoInitialize()
        self.dm = DM(dll_path=os.path.join(self.exe_dir_path,"dm.dll"))
        print(self.dm.GetBasePath())
        # self.dm.Un_reg()

        # 关闭等待窗口
        self.wait_window.close()
        # 监听键盘
        keyboard.wait()

    def listen_track_stop(self):
        print("按住了ctrl+c")
        try:
            self.track.stop()
        except Exception:
            traceback.print_exc()

    def edit_track(self):
        Track_window(height=280, pre_window=self, flag=1)

    def new_track(self):
        Track_window(height=280, pre_window=self, flag=0)

    def start(self):
        self.track = Track(self)
        self.track.start()

    def alpha(self):
        Alpha_window(height=40, pre_window=self)

    def help(self, **kwargs):
        Help_window(width=1000,
                    height=600,
                    path=self.exe_dir_path + "/README.md")

class Track_window(object):
    def __init__(self, height, pre_window, **kwargs):
        self.root = tk.Toplevel()
        self.root.iconbitmap("favicon.ico")
        self.root.wm_attributes('-topmost', 1)

        self.pre_window = pre_window
        self.pre_window_root = pre_window.root
        self.width, self.height = pre_window.width, height
        self.exe_dir_path = pre_window.exe_dir_path
        self.file_name = self.pre_window.comboxlist.get()
        self.flag = kwargs["flag"]

        self.pre_window_root_x, self.pre_window_root_y, self.pre_window_root_w, self.pre_window_root_h = \
            self.pre_window_root.winfo_x(), \
            self.pre_window_root.winfo_y(), \
            self.pre_window_root.winfo_width(), \
            self.pre_window_root.winfo_height()
        self.width_adjust = self.pre_window_root_x
        self.height_adjust = self.pre_window_root_y + self.pre_window_root_h + 40

        self.root.geometry("%dx%d+%d+%d" % (self.width, self.height, self.width_adjust, self.height_adjust))

        # 布局
        self.frame_bottom2 = Frame(self.root)
        self.frame_bottom2.pack(side=BOTTOM, padx=20, pady=5, expand=True, fill=X)
        self.frame_top = Frame(self.root)
        self.frame_top.pack(side=TOP, padx=20, pady=10)
        self.frame_middle = Frame(self.root)
        self.frame_middle.pack(side=TOP, padx=20, pady=5)

        # 轨迹名称
        ttk.Label(self.frame_top, text="轨迹名称").pack(side=tk.LEFT, padx=5, pady=2)
        self.track_name_str = tk.StringVar()
        self.track_name = ttk.Entry(self.frame_top,
                                    validate="focus",
                                    validatecommand=self.clear,
                                    textvariable=self.track_name_str)
        self.track_name.pack(side=tk.LEFT, fill="x", expand=True)
        ttk.Label(self.frame_top, text=".txt").pack(side=tk.LEFT, padx=2, pady=2)
        tk.Label(self.frame_top, state="disable", width=1000).pack(side=tk.LEFT, expand=True, fill=X)

        # 轨迹内容 n代表向上对齐
        ttk.Label(self.frame_middle, text="轨迹内容").pack(anchor="n", side=tk.LEFT, padx=5, pady=2)
        self.track_content = ScrolledText(self.frame_middle)
        self.track_content.pack(side=tk.LEFT)
        tk.Label(self.frame_middle, state="disable", width=1000).pack(side=tk.LEFT, expand=True, fill=X)

        # 完成按钮
        self.save_task_photo_image = ImageTk.PhotoImage(
            Image.open(self.exe_dir_path + "/img/" + "确认.png").resize((25, 25)))
        self.save_task_button = tk.Button(self.frame_bottom2, command=self.ok,
                                          text="完成",
                                          image=self.save_task_photo_image,
                                          relief="flat", overrelief="groove")
        self.save_task_button.pack(side=tk.RIGHT)

        # 删除按钮
        self.del_task_photo_image = ImageTk.PhotoImage(
            Image.open(self.exe_dir_path + "/img/" + "24gl-trash2.png").resize((25, 25)))
        self.del_task_button = tk.Button(self.frame_bottom2, command=self.del_task,
                                         text="完成",
                                         image=self.del_task_photo_image,
                                         relief="flat", overrelief="groove")
        self.del_task_button.pack(side=tk.RIGHT)

        if self.flag == 1:
            self.root.title('修改轨迹')
            self.track_name.insert(0, self.file_name[:-4])
            with open(self.exe_dir_path + "/track/" + self.file_name, "r", encoding="utf8") as f:
                track_str = f.read()
                self.track_content.insert(END, track_str)
        else:
            self.root.title("新建轨迹")
            self.track_name.insert(0, "输入轨迹名称")
            self.del_task_button.pack_forget()

        self.root.mainloop()

    def ok(self):
        if self.flag == 1:
            os.remove(self.exe_dir_path + "/track/" + self.file_name)
        with open(self.exe_dir_path + "/track/" + self.track_name_str.get() + ".txt", "w", encoding="utf-8") as f:
            track_content_get = self.track_content.get(1.0, END)
            f.write(track_content_get)
        self.pre_window.refresh_files()
        self.root.destroy()

    def clear(self):
        if "输入轨迹名称" in self.track_name.get():
            self.track_name.delete(0, "end")

    def del_task(self):
        os.remove(self.exe_dir_path + "/track/" + self.file_name)
        self.pre_window.refresh_files()
        self.root.destroy()

class Alpha_window(object):
    def __init__(self, height, pre_window, **kwargs):
        self.root = tk.Toplevel()
        self.root.title('调整透明度')
        self.root.iconbitmap("favicon.ico")
        self.root.wm_attributes('-topmost', 1)

        self.pre_window = pre_window
        self.pre_window_root = pre_window.root
        self.width = pre_window.width
        self.height = height

        self.pre_window_root_x, self.pre_window_root_y, self.pre_window_root_w, self.pre_window_root_h = \
            self.pre_window_root.winfo_x(), \
            self.pre_window_root.winfo_y(), \
            self.pre_window_root.winfo_width(), \
            self.pre_window_root.winfo_height()
        self.width_adjust = self.pre_window_root_x
        self.height_adjust = self.pre_window_root_y + self.pre_window_root_h + 40

        self.root.geometry("%dx%d+%d+%d" % (self.width, self.height, self.width_adjust, self.height_adjust))

        # 布局
        self.frame_bottom = Frame(self.root)
        self.frame_bottom.pack(side=BOTTOM, fill="x", expand=True, padx=10, pady=5)

        self.scale = ttk.Scale(self.frame_bottom, from_=0, to=100,
                               command=self.set_alpha,
                               value=90)
        self.scale.pack(side=tk.LEFT, padx=5, pady=2, expand=True, fill=X)
        self.scale.set(float(self.pre_window_root.wm_attributes("-alpha")) * 100)
        self.root.mainloop()

    def set_alpha(self, i):
        self.pre_window_root.attributes('-alpha', float(i) / 100)

class Help_window(object):
    def __init__(self, width, height, path):
        self.root = tk.Toplevel()
        self.root.title('使用说明')
        self.root.iconbitmap("favicon.ico")
        self.path = path

        # 居中显示
        self.width, self.height = width, height
        win_width = self.root.winfo_screenwidth()
        win_higth = self.root.winfo_screenheight()
        width_adjust = (win_width - width) / 2
        higth_adjust = (win_higth - height) / 2
        self.root.geometry("%dx%d+%d+%d" % (width, height, width_adjust, higth_adjust))

        self.frame_bottom = ttk.Frame(self.root)
        self.frame_bottom.pack(side=tk.BOTTOM, fill=BOTH, expand=False)
        self.frame_top = ttk.Frame(self.root, padding=20)
        self.frame_top.pack(side=tk.TOP, fill=BOTH, expand=True)

        self.HtmlView = TkHtmlView(self.frame_top, background="white")
        self.HtmlView.pack(fill='both', expand=True)

        self.filename = tk.StringVar()
        ttk.Entry(self.frame_bottom, textvariable=self.filename).pack(side=tk.LEFT, padx=20, pady=10, fill='x',
                                                                      expand=True)
        ttk.Button(self.frame_bottom, text='选择文件', command=self.open_file).pack(side=tk.LEFT, padx=20, pady=10)

        # 加载默认md文件
        self.p = Thread(target=self.init_file)
        self.p.start()

        self.root.mainloop()

    def init_file(self):
        with open(self.path, encoding='utf-8') as f:
            self.filename.set(self.path)
            md2html = Markdown()
            html = md2html.convert(f.read())
            self.HtmlView.set_html(html)

    def open_file(self):
        path = askopenfilename()
        if not path:
            return
        with open(path, encoding='utf-8') as f:
            self.filename.set(path)
            md2html = Markdown()
            html = md2html.convert(f.read())
            print(html)
            self.HtmlView.set_html(html)

class Wait_window(object):
    def __init__(self, height, pre_window):
        self.root = tk.Toplevel()
        self.root.title('初始化')
        self.root.iconbitmap("favicon.ico")
        self.root.wm_attributes('-topmost', 1)

        self.pre_window = pre_window
        self.pre_window_root = pre_window.root
        self.width = pre_window.width
        self.height = height

        self.pre_window_root_x, self.pre_window_root_y, self.pre_window_root_w, self.pre_window_root_h = \
            self.pre_window_root.winfo_x(), \
            self.pre_window_root.winfo_y(), \
            self.pre_window_root.winfo_width(), \
            self.pre_window_root.winfo_height()
        self.width_adjust = self.pre_window_root_x
        self.height_adjust = self.pre_window_root_y + self.pre_window_root_h + 40

        self.root.geometry("%dx%d+%d+%d" % (self.width, self.height, self.width_adjust, self.height_adjust))

        # 布局
        self.frame_bottom = Frame(self.root)
        self.frame_bottom.pack(side=BOTTOM, padx=15, pady=10, expand=True, fill=X)
        self.frame_top = Frame(self.root)
        self.frame_top.pack(side=TOP, padx=5, pady=10)

        # 进度条
        self.bar = ttk.Progressbar(self.frame_bottom, mode="indeterminate", orient=tk.HORIZONTAL)
        self.bar.pack(expand=True, fill=X)
        self.bar.start(10)

        # 提示内容
        self.content = tk.Label(self.frame_top, text="正在初始化,请不要操作，请耐心等待......")
        self.content.pack()

        # self.root.mainloop()

    def close(self):
        self.root.destroy()

class Setting_window(object):
    def __init__(self, height, pre_window, **kwargs):
        self.root = tk.Toplevel()
        self.root.title('设置')
        self.root.iconbitmap("favicon.ico")
        self.root.wm_attributes('-topmost', 1)

        self.exe_dir_path = pre_window.exe_dir_path

        self.pre_window = pre_window
        self.pre_window_root = pre_window.root
        self.width = pre_window.width
        self.height = height

        self.pre_window_root_x, self.pre_window_root_y, self.pre_window_root_w, self.pre_window_root_h = \
            self.pre_window_root.winfo_x(), \
            self.pre_window_root.winfo_y(), \
            self.pre_window_root.winfo_width(), \
            self.pre_window_root.winfo_height()
        self.width_adjust = self.pre_window_root_x
        self.height_adjust = self.pre_window_root_y + self.pre_window_root_h + 40
        self.root.geometry("%dx%d+%d+%d" % (self.width, self.height, self.width_adjust, self.height_adjust))

        self.my_dict = pre_window.my_dict
        self.coordinate_x = tk.StringVar()
        self.coordinate_y = tk.StringVar()
        self.mode_combobox_str = tk.StringVar()
        self.title_str = tk.StringVar()

        self.coordinate = self.my_dict["coordinate"][0]
        self.coordinate_x.set(self.coordinate[0])
        self.coordinate_y.set(self.coordinate[1])
        self.mode_combobox_str.set(self.my_dict["mode"][0])
        self.title_str.set(self.my_dict["title"][0])

        # 布局
        self.frame_top = Frame(self.root)
        self.frame_top.pack(side=TOP, padx=20, pady=10)

        self.frame_middle2 = Frame(self.root)
        self.frame_middle2.pack(side=TOP, padx=20, pady=1)

        self.frame_middle = Frame(self.root)
        self.frame_middle.pack(side=TOP, padx=20, pady=10)

        self.frame_bottom = Frame(self.root)
        self.frame_bottom.pack(side=BOTTOM, padx=20, expand=True, fill=X)

        # 基准
        ttk.Label(self.frame_top, text="基准坐标：").pack(side=tk.LEFT, padx=5, pady=2)
        self.coordinate_x_entry = ttk.Entry(self.frame_top, width=5, textvariable=self.coordinate_x)
        self.coordinate_x_entry.pack(side=tk.LEFT, padx=3)
        self.coordinate_y_entry = ttk.Entry(self.frame_top, width=5, textvariable=self.coordinate_y)
        self.coordinate_y_entry.pack(side=tk.LEFT, padx=3)
        tk.Label(self.frame_top, state="disable", width=1000).pack(side=tk.LEFT, expand=True, fill=X)

        # 模式
        ttk.Label(self.frame_middle, text="启动模式：").pack(side=tk.LEFT, padx=5, pady=2)
        self.mode_combobox = ttk.Combobox(self.frame_middle, width=26, values=["有蜂鸣器声音", "没有蜂鸣器声音"], state="readonly",
                                          textvariable=self.mode_combobox_str)
        self.mode_combobox.pack(side=tk.LEFT, padx=0, pady=2)
        tk.Label(self.frame_middle, state="disable", width=1000).pack(side=tk.LEFT, expand=True, fill=X)

        # 标题
        ttk.Label(self.frame_middle2, text="窗口标题：").pack(side=tk.LEFT, padx=5, pady=2)
        self.title_entry = ttk.Entry(self.frame_middle2, width=10, textvariable=self.title_str)
        self.title_entry.pack(side=tk.LEFT, padx=3)
        tk.Label(self.frame_middle2, text="模糊匹配", width=1000).pack(side=tk.LEFT, expand=True, fill=X)

        # 按钮
        self.cancel_image = ImageTk.PhotoImage(Image.open(self.exe_dir_path + "/img/" + "取消.png").resize((18, 18)))
        self.cancel_button = tk.Button(self.frame_bottom,
                                       command=self.cancel,
                                       image=self.cancel_image,
                                       relief="flat",
                                       overrelief="groove")
        self.cancel_button.pack(side=tk.RIGHT, padx=5, pady=2)

        self.ok_image = ImageTk.PhotoImage(Image.open(self.exe_dir_path + "/img/" + "确认.png").resize((18, 18)))
        self.ok_button = tk.Button(self.frame_bottom,
                                   command=self.ok,
                                   image=self.ok_image,
                                   relief="flat",
                                   overrelief="groove")
        self.ok_button.pack(side=tk.RIGHT, padx=5, pady=2)

        self.root.mainloop()

    def cancel(self):
        self.root.destroy()

    def ok(self):
        self.my_dict["coordinate"] = [(eval(self.coordinate_x.get()), eval(self.coordinate_y.get()))]
        self.my_dict["mode"] = [self.mode_combobox_str.get()]
        self.my_dict["title"] = [self.title_str.get()]

        self.root.destroy()

class Track(threading.Thread):
    def __init__(self, pre_window, *args, **kwargs):
        super(Track, self).__init__(*args, **kwargs)
        self.__flag = threading.Event()  # 用于暂停线程的标识
        self.__flag.set()  # 设置为True
        self.__running = threading.Event()  # 用于停止线程的标识
        self.__running.set()  # 将running设置为True

        self.pre_window = pre_window
        self.dm = pre_window.dm
        self.exe_dir_path = pre_window.exe_dir_path
        self.my_dict = pre_window.my_dict

        self.file_name = self.pre_window.comboxlist.get()
        self.command_dict_list = []
        self.read_file(file_name=self.exe_dir_path + "/track/" + self.file_name)

    def read_file(self, file_name):
        self.step_dict_list = []
        with open(file_name, "r", encoding="utf8") as f:
            for line in f.readlines():
                linestr = line.strip()
                if linestr != "":
                    linestrlist = linestr.split("-")
                    self.step_dict_list.append({"command": linestrlist[0], "content": linestrlist})

    def run(self):
        if self.ready() == 0:
            return
        for step_dict in self.step_dict_list:
            self.__flag.wait()  # 为True时立即返回, 为False时阻塞直到内部的标识位为True后返回
            if self.__running.isSet():

                self.step_dict = step_dict
                print(step_dict)
                StepCommand(self.dm, self.hwnd, self.coordinate, self.step_dict)

            else:
                break

    def ready(self):
        """
        操作前的准备
        :return:
        """
        self.coordinate = self.my_dict["coordinate"][0]
        self.title = self.my_dict["title"][0]
        if self.my_dict["mode"][0] == "有蜂鸣器声音":
            self.dm.Beep()

        # 找到窗体
        self.hwnd = self.dm.FindWindow("", self.title)
        if self.hwnd == 0:
            tkinter.messagebox.askokcancel(title='没有找到窗口',
                                           message='确定你的游戏是否运行？或者你的窗口标题是否正确？')
            return 0
        else:
            # 激活窗体
            self.dm.SetWindowState(self.hwnd, 1)
            return 1

    def stop(self):
        self.__flag.set()  # 将线程从暂停状态恢复, 如何已经暂停的话
        self.__running.clear()  # 设置为False

class Test_window(object):
    def __init__(self, height, pre_window, **kwargs):
        self.root = tk.Toplevel()
        self.root.title('测试轨迹')
        self.root.iconbitmap("favicon.ico")
        self.root.wm_attributes('-topmost', 1)

        self.my_dict = pre_window.my_dict
        self.pre_window = pre_window
        self.pre_window_root = pre_window.root
        self.exe_dir_path = pre_window.exe_dir_path
        self.width = pre_window.width
        self.height = height
        self.dm = pre_window.dm

        self.pre_window_root_x, self.pre_window_root_y, self.pre_window_root_w, self.pre_window_root_h = \
            self.pre_window_root.winfo_x(), \
            self.pre_window_root.winfo_y(), \
            self.pre_window_root.winfo_width(), \
            self.pre_window_root.winfo_height()
        self.width_adjust = self.pre_window_root_x
        self.height_adjust = self.pre_window_root_y + self.pre_window_root_h + 40

        self.root.geometry("%dx%d+%d+%d" % (self.width, self.height, self.width_adjust, self.height_adjust))

        # 布局
        self.frame_top = Frame(self.root)
        self.frame_top.pack(side=TOP, pady=5, padx=15)
        self.frame_middle = Frame(self.root)
        self.frame_middle.pack(side=TOP, pady=5, padx=15)
        self.frame_middle2 = Frame(self.root)
        self.frame_middle2.pack(side=TOP, pady=5, padx=15)
        self.frame_middle3 = Frame(self.root)
        self.frame_middle3.pack(side=TOP, pady=5, padx=15)
        self.frame_bottom = Frame(self.root)
        self.frame_bottom.pack(side=BOTTOM, padx=20, pady=5, expand=True, fill=X)

        # 只能右侧，左侧用框架控制
        ttk.Label(self.frame_top, text="指令：").pack(side=tk.LEFT, pady=3)
        self.command_comvalue = tkinter.StringVar()
        self.comboxlist = ttk.Combobox(self.frame_top, textvariable=self.command_comvalue, width=27)
        self.comboxlist["values"] = ("请选择指令")
        self.comboxlist['state'] = 'readonly'
        self.comboxlist.current(0)
        self.comboxlist.pack(side=tk.LEFT, pady=3)
        tk.Label(self.frame_top, state="disable", width=1000).pack(side=tk.LEFT, expand=True, fill=X)
        self.comboxlist.bind("<<ComboboxSelected>>", self.manage)

        ttk.Label(self.frame_middle, text="步长：").pack(side=tk.LEFT, pady=3)
        self.step_value = tkinter.StringVar()
        self.step_entry = ttk.Entry(self.frame_middle, textvariable=self.step_value, width=20)
        self.step_entry.pack(side=tk.LEFT, pady=3)
        tk.Label(self.frame_middle, text="单位是像素").pack(side=tk.LEFT)
        tk.Label(self.frame_middle, state="disable", width=1000).pack(side=tk.LEFT, expand=True, fill=X)

        ttk.Label(self.frame_middle2, text="时长：").pack(side=tk.LEFT, pady=3)
        self.duration_value = tkinter.StringVar()
        self.duration_entry = ttk.Entry(self.frame_middle2, textvariable=self.duration_value, width=20)
        self.duration_entry.pack(side=tk.LEFT, pady=3)
        tk.Label(self.frame_middle2, text="单位是毫秒").pack(side=tk.LEFT)
        tk.Label(self.frame_middle2, state="disable", width=1000).pack(side=tk.LEFT, expand=True, fill=X)

        ttk.Label(self.frame_middle3, text="生成：").pack(side=tk.LEFT, pady=3)
        self.output_value = tkinter.StringVar()
        self.output_entry = ttk.Entry(self.frame_middle3, textvariable=self.output_value, width=27)
        self.output_entry.pack(side=tk.LEFT, pady=3)
        tk.Label(self.frame_middle3, state="disable", width=1000).pack(side=tk.LEFT, expand=True, fill=X)

        # 确定按钮
        self.do_photo_image = ImageTk.PhotoImage(
            Image.open(self.exe_dir_path + "/img/" + "确认.png").resize((25, 25)))
        self.do_button = tk.Button(self.frame_bottom,
                                   command=self.work,
                                   text="确定",
                                   image=self.do_photo_image,
                                   relief="flat", overrelief="groove")
        self.do_button.pack(side=tk.RIGHT)

        # 撤回按钮
        self.undo_photo_image = ImageTk.PhotoImage(
            Image.open(self.exe_dir_path + "/img/" + "undo.png").resize((25, 25)))
        self.undo_button = tk.Button(self.frame_bottom,
                                     command=self.undo,
                                     text="撤回",
                                     image=self.undo_photo_image,
                                     relief="flat", overrelief="groove")
        self.undo_button.pack(side=tk.RIGHT)

        self.key_single_list = ["复位相机", "朝向脸部", "朝向胸部", "朝向跨下", "加速抽送", "减速抽送"]
        self.key_press_list = ["向前平移", "向后平移", "向左平移", "向右平移", "向上平移", "向下平移", "旋转视角"]
        self.left_click_list = ["向上拖动", "向下拖动", "向左拖动", "向右拖动", "左上拖动", "左下拖动", "右上拖动", "右下拖动"]
        # self.custom_list = ["自定义左键", "自定义右键"]
        self.custom_list = []
        self.all_list = self.key_single_list + self.key_press_list + self.left_click_list + self.custom_list
        self.comboxlist.config(value=self.all_list)

        self.root.mainloop()

    def manage(self, event):
        self.command_comvalue_str = self.command_comvalue.get()
        if self.command_comvalue_str in self.key_single_list:
            self.step_entry.config(state=tk.DISABLED)
            self.duration_entry.config(state=tk.DISABLED)
            self.undo_button.pack_forget()

        elif self.command_comvalue_str in self.key_press_list:
            self.step_entry.config(state=tk.DISABLED)
            self.duration_entry.config(state=tk.NORMAL)
            self.undo_button.pack(side=tk.RIGHT)

        elif self.command_comvalue_str in self.left_click_list:
            self.step_entry.config(state=tk.NORMAL)
            self.duration_entry.config(state=tk.NORMAL)
            self.undo_button.pack(side=tk.RIGHT)

    def undo(self):
        self.output_value_str = self.output_value.get()

        self.output_value_str_ = ""
        for o in self.output_value_str:
            if o == "上":
                self.output_value_str_ = self.output_value_str_ + "下"
            elif o == "下":
                self.output_value_str_ = self.output_value_str_ + "上"
            elif o == "左":
                self.output_value_str_ = self.output_value_str_ + "右"
            elif o == "右":
                self.output_value_str_ = self.output_value_str_ + "左"
            elif o == "前":
                self.output_value_str_ = self.output_value_str_ + "后"
            elif o == "后":
                self.output_value_str_ = self.output_value_str_ + "前"
            else:
                self.output_value_str_ = self.output_value_str_ + o

        self.begin(self.output_value_str_.split("-"))

    def work(self):
        # 生成指令
        self.command_comvalue_str = self.command_comvalue.get()
        if self.command_comvalue_str in self.key_single_list:
            self.command_comvalue_str = self.command_comvalue.get()
            self.output_value.set(self.command_comvalue_str)
        elif self.command_comvalue_str in self.key_press_list:
            self.command_comvalue_str = self.command_comvalue.get() + "-" + self.duration_value.get()
            self.output_value.set(self.command_comvalue_str)
        elif self.command_comvalue_str in self.left_click_list:
            self.command_comvalue_str = self.command_comvalue.get() + "-" + self.step_value.get() + "-" + self.duration_value.get()
            self.output_value.set(self.command_comvalue_str)

        self.begin(self.command_comvalue_str.split("-"))

    def begin(self, linestrlist):
        if self.ready() == 0:
            return
        self.step_dict = {"command": linestrlist[0], "content": linestrlist}
        print(self.step_dict)
        StepCommand(self.dm, self.hwnd, self.coordinate, self.step_dict)

    def ready(self):
        """
        操作前的准备
        :return:
        """
        self.coordinate = self.my_dict["coordinate"][0]
        self.title = self.my_dict["title"][0]
        if self.my_dict["mode"][0] == "有蜂鸣器声音":
            self.dm.Beep()

        # 找到窗体
        self.hwnd = self.dm.FindWindow("", self.title)
        if self.hwnd == 0:
            tkinter.messagebox.askokcancel(title='没有找到窗口',
                                           message='确定你的游戏是否运行？或者你的窗口标题是否正确？')
            return 0
        else:
            # 激活窗体
            self.dm.SetWindowState(self.hwnd, 1)
            return 1

class StepCommand:
    '''
    向指定窗体发送命令
    '''

    def __init__(self, dm, hwnd, coordinate, step_dict):
        self.dm = dm
        self.hwnd = hwnd

        (self.center_x, self.center_y) = coordinate
        self.dm.MoveTo(self.center_x, self.center_y)

        flag = self.dm.GetWindowState(self.hwnd, 1)
        if not flag:
            self.dm.SetWindowState(self.hwnd, 1)
        # 按键
        if step_dict["command"] == "复位相机":
            self.cam_init(step_dict)
        elif step_dict["command"] == "朝向脸部":
            self.cam_to_face(step_dict)
        elif step_dict["command"] == "朝向胸部":
            self.cam_to_chest(step_dict)
        elif step_dict["command"] == "朝向跨下":
            self.cam_to_crawl(step_dict)
        elif step_dict["command"] == "加速抽送":
            self.speed_up(step_dict)
        elif step_dict["command"] == "减速抽送":
            self.speed_down(step_dict)

        # 按键-时长
        elif step_dict["command"] == "向前平移":
            self.translation_front(step_dict)
        elif step_dict["command"] == "向后平移":
            self.translation_back(step_dict)
        elif step_dict["command"] == "向左平移":
            self.translation_left(step_dict)
        elif step_dict["command"] == "向右平移":
            self.translation_right(step_dict)
        elif step_dict["command"] == "向上平移":
            self.translation_up(step_dict)
        elif step_dict["command"] == "向下平移":
            self.translation_down(step_dict)
        elif step_dict["command"] == "旋转视角":
            self.rotate(step_dict)

        # 左击-拖动-时长
        elif step_dict["command"] == "向上拖动":
            self.turn_up(step_dict)
        elif step_dict["command"] == "向下拖动":
            self.turn_down(step_dict)
        elif step_dict["command"] == "向左拖动":
            self.turn_left(step_dict)
        elif step_dict["command"] == "向右拖动":
            self.turn_right(step_dict)
        elif step_dict["command"] == "左上拖动":
            self.turn_left_up(step_dict)
        elif step_dict["command"] == "左下拖动":
            self.turn_left_down(step_dict)
        elif step_dict["command"] == "右上拖动":
            self.turn_right_up(step_dict)
        elif step_dict["command"] == "右下拖动":
            self.turn_right_down(step_dict)

        # 自定义
        elif step_dict["command"] == "自定义左键":
            self.custom_left(step_dict)
        elif step_dict["command"] == "自定义右键":
            self.custom_right(step_dict)

    # 单纯按键类
    # 复位相机
    def cam_init(self, step_dict):
        self.dm.KeyPressChar("r")

    # 朝向脸部
    def cam_to_face(self, step_dict):
        self.dm.KeyPressChar("q")

    # 朝向胸部
    def cam_to_chest(self, step_dict):
        self.dm.KeyPressChar("w")

    # 朝向跨下
    def cam_to_crawl(self, step_dict):
        self.dm.KeyPressChar("e")

    # 加速抽送
    def speed_up(self, step_dict):
        self.dm.WheelUp()

    # 减速抽送
    def speed_down(self, step_dict):
        self.dm.WheelDown()

    # 按键时间类
    # 向后平移
    def translation_back(self, step_dict):
        duration = eval(step_dict["content"][1])
        s_duration = round(duration / 1000, 4)
        self.dm.KeyDownChar("down")
        time.sleep(s_duration)
        self.dm.KeyUpChar("down")

    # 向前平移
    def translation_front(self, step_dict):
        duration = eval(step_dict["content"][1])
        s_duration = round(duration / 1000, 4)
        self.dm.KeyDownChar("up")
        time.sleep(s_duration)
        self.dm.KeyUpChar("up")

    # 向左平移
    def translation_left(self, step_dict):
        duration = eval(step_dict["content"][1])
        s_duration = round(duration / 1000, 4)
        self.dm.KeyDownChar("left")
        time.sleep(s_duration)
        self.dm.KeyUpChar("left")

    # 向右平移
    def translation_right(self, step_dict):
        duration = eval(step_dict["content"][1])
        s_duration = round(duration / 1000, 4)
        self.dm.KeyDownChar("right")
        time.sleep(s_duration)
        self.dm.KeyUpChar("right")

    # 向上平移
    def translation_up(self, step_dict):
        duration = eval(step_dict["content"][1])
        s_duration = round(duration / 1000, 4)
        self.dm.KeyDownChar("pgup")
        time.sleep(s_duration)
        self.dm.KeyUpChar("pgup")

    # 向下平移
    def translation_down(self, step_dict):
        duration = eval(step_dict["content"][1])
        s_duration = round(duration / 1000, 4)
        self.dm.KeyDownChar("pgdn")
        time.sleep(s_duration)
        self.dm.KeyUpChar("pgdn")

    # 旋转视角
    def rotate(self, step_dict):
        duration = eval(step_dict["content"][1])
        s_duration = round(duration / 1000, 4)
        self.dm.KeyDownChar("\\")
        time.sleep(s_duration)
        self.dm.KeyUpChar("\\")

    # 鼠标左类
    # 向下拖动
    def turn_down(self, step_dict):
        length = eval(step_dict["content"][1])
        duration = eval(step_dict["content"][2])
        self.dm.LeftDown()
        pre_duration = round(duration / 1000 / length, 4)
        for i in range(length):
            time.sleep(pre_duration)
            self.dm.MoveR(0, 1)
        self.dm.LeftUp()

    # 向上拖动
    def turn_up(self, step_dict):
        length = eval(step_dict["content"][1])
        duration = eval(step_dict["content"][2])
        self.dm.LeftDown()
        pre_duration = round(duration / 1000 / length, 4)
        for i in range(length):
            time.sleep(pre_duration)
            self.dm.MoveR(0, -1)
        self.dm.LeftUp()

    # 向左拖动
    def turn_left(self, step_dict):
        length = eval(step_dict["content"][1])
        duration = eval(step_dict["content"][2])
        self.dm.LeftDown()
        pre_duration = round(duration / 1000 / length, 4)
        for i in range(length):
            time.sleep(pre_duration)
            self.dm.MoveR(-1, 0)
        self.dm.LeftUp()

    # 向右拖动
    def turn_right(self, step_dict):
        length = eval(step_dict["content"][1])
        duration = eval(step_dict["content"][2])
        self.dm.LeftDown()
        pre_duration = round(duration / 1000 / length, 4)
        for i in range(length):
            time.sleep(pre_duration)
            self.dm.MoveR(1, 0)
        self.dm.LeftUp()

    # 左上拖动
    def turn_left_up(self, step_dict):
        length = eval(step_dict["content"][1])
        duration = eval(step_dict["content"][2])
        self.dm.LeftDown()
        pre_duration = round(duration / 1000 / length, 4)
        for i in range(length):
            time.sleep(pre_duration)
            self.dm.MoveR(-1, -1)
        self.dm.LeftUp()

    # 左下拖动
    def turn_left_down(self, step_dict):
        length = eval(step_dict["content"][1])
        duration = eval(step_dict["content"][2])
        self.dm.LeftDown()
        pre_duration = round(duration / 1000 / length, 4)
        for i in range(length):
            time.sleep(pre_duration)
            self.dm.MoveR(-1, 1)
        self.dm.LeftUp()

    # 右上拖动
    def turn_right_up(self, step_dict):
        length = eval(step_dict["content"][1])
        duration = eval(step_dict["content"][2])
        self.dm.LeftDown()
        pre_duration = round(duration / 1000 / length, 4)
        for i in range(length):
            time.sleep(pre_duration)
            self.dm.MoveR(1, -1)
        self.dm.LeftUp()

    # 右下拖动
    def turn_right_down(self, step_dict):
        length = eval(step_dict["content"][1])
        duration = eval(step_dict["content"][2])
        self.dm.LeftDown()
        pre_duration = round(duration / 1000 / length, 4)
        for i in range(length):
            time.sleep(pre_duration)
            self.dm.MoveR(1, 1)
        self.dm.LeftUp()

    # 自定义左键
    def custom_left(self, step_dict):
        pass

    # 自定义右键
    def custom_right(self, step_dict):
        pass

if __name__ == "__main__":
    main = Main_window(title="ZOD小导演",
                       icon="favicon.ico",
                       alpha=0.9,
                       topmost=1,
                       bg="white",
                       width=300,
                       height=70,
                       width_adjust=10,
                       higth_adjust=5)

# pyinstaller -F -i "C:\Users\Gao yongxian\PycharmProjects\Zod_director\pack\favicon.ico" "C:\Users\Gao yongxian\PycharmProjects\Zod_director\zod.py" -w


"""Prepare the IAM handwriting dataset for ESPnet ASR training

Usage:
    python local/data_prep.py
        [--feature_dim 100]
        [--downsampling_factor 0.5]

Expects data to be in:
    downloads/
        lines.txt      # labels for IAM dataset (from ascii.tgz)
        lines/
            */*/*.png  # "lines" data for IAM dataset (from lines.tgz)
        train.txt      # id's for train/valid/test splits
        valid.txt
        test.txt

Required packages:
    Pillow
"""
import argparse
import os

import numpy as np
from PIL import Image

from espnet.utils.cli_writers import file_writer_helper

def prepare_text(lines_file_path, output_dir, split_ids):
    """Create 'text' file (map of ids to transcripts) in Kaldi format

    Parameters
    ----------
    lines_file_path : str
        The file path of the "lines.txt" label file of the IAM dataset
    output_dir : str
        The folder path for output, e.g. data/
    split_ids : list of str
        a list of ids to process, e.g. train/valid/test splits

    Returns
    -------
    skipped_ids : list of str
        a list of ids that were skipped,
        e.g. due to having an empty transcription
    """
    output_lines = []
    skipped_ids = []
    with open(lines_file_path) as lines_file:
        for line in lines_file.readlines():
            # skip comment lines
            if line[0] == "#":
                continue

            line_split = line.strip().split()

            # extract line ID
            line_id = line_split[0]

            if line_id in split_ids:
                # extract and format transcription into Kaldi style
                transcription = " ".join(line_split[8:])
                transcription = transcription.replace("|", " ")
                transcription = transcription.strip()

                if transcription == "":
                    print(f"Line {line_id} has an empty transcript, skipping")
                    skipped_ids.append(line_id)
                    continue

                output_lines.append(f"{line_id} {transcription}\n")

    output_lines.sort()

    with open(os.path.join(output_dir, "text"), "w") as out_file:
        out_file.writelines(output_lines)

    return skipped_ids

def prepare_utt2spk_spk2utt(output_dir, split_ids, ids_to_skip=[]):
    """Create (dummy) utt2spk and spk2utt files to satisfy Kaldi format

    Parameters
    ----------
    output_dir : str
        The folder path for output, e.g. data/
    split_ids : list of str
        a list of example ids to process, e.g. train/valid/test splits
    ids_to_skip : list of str
        A list of ids to exclude from the output,
        e.g. to ignore previously skipped ids due to empty transcript
    """
    output_lines = [f"{x} {x}\n" for x in split_ids if x not in ids_to_skip]
    output_lines.sort()

    with open(os.path.join(output_dir, "utt2spk"), "w") as out_file:
        out_file.writelines(output_lines)

    with open(os.path.join(output_dir, "spk2utt"), "w") as out_file:
        out_file.writelines(output_lines)

def prepare_feats(
    img_dir,
    output_dir,
    split_ids,
    ids_to_skip=[],
    feature_dim=100,
    downsampling_factor=0.5,
):
    """Create feats.scp file from OCR images

    Parameters
    ----------
    output_dir : str
        The folder path for output, e.g. data/
    split_ids : list of str
        a list of ids to process, e.g. train/valid/test splits
    ids_to_skip : list of str
        A list of ids to exclude from the output,
        e.g. to ignore previously skipped ids due to empty transcript
    feature_dim : int (default=100)
        The hidden dimension for each feature matrix,
        all images are resized to this height
    downsampling_factor : float (default=0.5)
        A multiplier for the width dimension (analogous to the 'time'
        dimension in ASR) of each image, used to reduce the length for
        faster training. Empirically, a value of 0.5 is found to achieve
        the best performance for this dataset
    """
    output_ark = os.path.join(output_dir, "feats.ark")
    output_scp = os.path.join(output_dir, "feats.scp")
    writer = file_writer_helper(
        wspecifier=f"ark,scp:{output_ark},{output_scp}",
        filetype="mat",
        write_num_frames=f"ark,t:{output_dir}/num_frames.txt",
        compress=False,
    )

    num_processed = 0
    total_length = 0

    for img_id in split_ids:
        if img_id in ids_to_skip:
            continue

        dir, subdir, index = img_id.split("-")
        img_path = os.path.join(
            img_dir, dir, f"{dir}-{subdir}", f"{dir}-{subdir}-{index}.png"
        )
        with Image.open(img_path) as img:
            # resize images to common height (feature_dim)
            # and downsample width by downsampling_factor
            aspect_ratio = img.width / img.height
            n_frames = int((aspect_ratio * feature_dim) * downsampling_factor)
            img = img.resize((n_frames, feature_dim))
            img_arr = np.array(img, dtype=np.float32).transpose()
            assert img_arr.shape[1] == feature_dim

            # write to data/output_dir/feats.scp
            writer[img_id] = img_arr

            # update counters for logging
            num_processed += 1
            total_length += img_arr.shape[0]

    print(
        f"Extracted features for {num_processed} examples "
        f"to {os.path.join(output_dir, 'feats.scp')},"
        f"average length is {total_length / num_processed:.02f}"
    )

if __name__ == "__main__":
    downloads_dir = "downloads/"
    data_dir = "data/"

    parser = argparse.ArgumentParser()
    parser.add_argument(
        "--feature_dim",
        type=int,
        default=100,
        help="Feature dimension to resize each image feature to",
    )
    parser.add_argument(
        "--downsampling_factor",
        type=float,
        default=0.5,
        help="Factor to downsample the length of each image feature to",
    )

    args = parser.parse_args()

    for split in ["train", "valid", "test"]:
        with open(os.path.join(downloads_dir, f"{split}.txt")) as split_file:
            split_ids = [line.strip() for line in split_file.readlines()]
            split_ids.sort()
            split_dir = os.path.join(data_dir, f"{split}/")
            os.makedirs(split_dir, exist_ok=True)

            lines_file_path = os.path.join(downloads_dir, "lines.txt")
            skipped_lines = prepare_text(lines_file_path, split_dir, split_ids)
            prepare_utt2spk_spk2utt(split_dir, split_ids, skipped_lines)
            prepare_feats(
                os.path.join(downloads_dir, "lines/"),
                split_dir,
                split_ids,
                skipped_lines,
                args.feature_dim,
                args.downsampling_factor,
            )


import json

import requests
from rest_framework import generics, status
from rest_framework.views import APIView
from rest_framework.response import Response
from decouple import config

from .permissions import IsAdmin
from .serializers import *

class CooperationRequestView(APIView):
    def post(self, request):
        if request.data['key'] != config('SHOP_SECRET_KEY'):
            return Response(status=status.HTTP_503_SERVICE_UNAVAILABLE)
        try:
            f = Factory.objects.get(title=request.data['factory'])
        except Factory.DoesNotExist or KeyError:
            return Response('Factory does not exist')
        if f.category_choicer != request.data['category']:
            return Response('It is impossible to cooperate because of category')

        s, created = ShopTitle.objects.get_or_create(title=request.data['shop'])

        try:
            queryset = []
            for product in json.loads(request.data['products']):
                if (product['quantity'] < 1) or (f.available - product['quantity'] < 0):
                    for elem in queryset:
                        elem.delete
                    return Response('It is too much')

                p, created = Product.objects.get_or_create(title=product['title'])

                d, created = DeliveryRequest.objects.get_or_create(shop=s, factory=f, product=p,
                                                                   quantity=product['quantity'])
                f.save()
                queryset.append(d)

        except KeyError:
            return Response('KeyError', status=status.HTTP_400_BAD_REQUEST)

        serializer = DeliveryRequestSerializer(queryset, context={'request': request}, many=True)
        return Response(serializer.data)

class DeliveryView(APIView):

    def post(self, request):
        try:
            if request.data['key'] != config('SECRET_KEY'):
                return Response(status=status.HTTP_503_SERVICE_UNAVAILABLE)
        except KeyError:
            return Response(status=status.HTTP_503_SERVICE_UNAVAILABLE)
        req = []
        for s in ShopTitle.objects.all():
            queryset = []
            for dr in DeliveryRequest.objects.filter(shop=s):
                d = {'title': dr.product.title,
                     'quantity': dr.quantity * dr.queue}
                queryset.append(d)

            data = {'key': config('SHOP_SECRET_KEY'),
                    'shop': s.title,
                    'products': json.dumps(queryset)}
            try:
                r = requests.post('http://172.18.0.1:80/api/shop/delivery/',
                                  data=data)
                for dr in DeliveryRequest.objects.filter(shop=s):
                    dr.queue = 1
                    dr.save()
            except OSError:
                for dr in DeliveryRequest.objects.filter(shop=s):
                    dr.queue += 1
                    dr.save()
                req.append(s.title)
        if not req:
            return Response(status=status.HTTP_201_CREATED)
        return Response(json.dumps(req), status=status.HTTP_404_NOT_FOUND)

class ListFactoryView(generics.ListAPIView):
    queryset = Factory.objects.all().order_by('-title')
    serializer_class = FactorySerializer


from aiohttp import web
from db import init_pg, close_pg

async def hello(request):
    return web.Response(text="Hello, world")

app = web.Application()
app.add_routes([web.get('/', hello)])
app.on_startup.append(init_pg)
app.on_cleanup.append(close_pg)

if __name__ == '__main__':
    web.run_app(app)


import bpy
import bmesh
from gorgious_utilities.attribute.tool import (
    get_bmesh_domain,
    get_attribute_size_and_name_from_attribute,
)

class GU_OT_attribute_set(bpy.types.Operator):
    bl_idname = "gu.attribute_set"
    bl_label = "Set attribute"
    bl_options = {"UNDO", "REGISTER"}
    mode: bpy.props.BoolVectorProperty()
    attribute_name: bpy.props.StringProperty()

    def execute(self, context):
        active_object = context.active_object
        attribute_name = (
            active_object.data.attributes.active.name if self.attribute_name is None else self.attribute_name
        )
        was_in_object_mode = active_object.mode == "OBJECT"
        if not was_in_object_mode:
            bpy.ops.object.editmode_toggle()

        if active_object.mode == "OBJECT":
            bm = bmesh.new()
            bm.from_mesh(active_object.data)
        else:
            bm = bmesh.from_edit_mesh(active_object.data)

        attribute = active_object.data.attributes[attribute_name]

        props = active_object.GUProps.attribute
        new_value = getattr(props, attribute.data_type)

        domain = get_bmesh_domain(bm, attribute.domain)

        size, attr_name = get_attribute_size_and_name_from_attribute(attribute)

        values = [None] * len(domain) * size
        attribute.data.foreach_get(attr_name, values)
        for i, vef in enumerate(domain):
            if not vef.select:
                continue
            if size > 1:
                for s in range(size):
                    values[i * size + s] = new_value[s]
            else:
                values[i] = new_value
        attribute.data.foreach_set(attr_name, values)

        active_object.data.update()

        if not was_in_object_mode:
            bpy.ops.object.editmode_toggle()

        return {"FINISHED"}


# -*- coding: utf-8 -*-
from bs4 import BeautifulSoup

import urllib2
import mechanize
from random import randint

class IPPool:

    def __init__(self):
        self.ips=[]
        self.br = mechanize.Browser()
        self.br.set_handle_robots(False)
        self.br.addheaders = [('User-agent', 'Mozilla/5.0 (Windows NT 6.2;\
                            WOW64) AppleWebKit/537.11 (KHTML, like Gecko)\
                            Chrome/23.0.1271.97 Safari/537.11')]
        self.add_ip_into_pool()
    def add_ip_into_pool(self):

        ip_pool_index = 'https://www.socks-proxy.net/'

        ip_pool_html = self.br.open(ip_pool_index).read()

        soup = BeautifulSoup(ip_pool_html,'lxml')

        result_table = soup.find('table',id='proxylisttable')

        tr_list = result_table.tbody.find_all('tr')
        for element in tr_list:
            ip_datas = element.find_all('td')
            if ip_datas[4].get_text() == 'Socks5':
                ip_address = '{0}://{1}:{2}'.format(ip_datas[4].get_text(),ip_datas[0].get_text(),ip_datas[1].get_text())
            # ip_address = ip_datas[4].get_text() + '://'+ ip_datas[0].get_text() + ':' + ip_datas[1].get_text
                print(ip_address)
                self.ips.append(ip_address)
            else:
                continue
    def random_ip_address(self):
        ip_index = randint(0,len(self.ips)-1)
        return self.ips[ip_index]

ip_pool = IPPool()
ip_pool.add_ip_into_pool()


import asyncio
import aiohttp

class WriteToFile:
    def __init__(self, filename):
        """Принимет имя файла"""
        self.filename = filename

    def __enter__(self):
        """Возвращает контекст (файловый объект)"""

#         Сохраняем в атрибут file_object
        self.file_object = open(self.filename, 'w')
        return self.file_object

    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.file_object:
            self.file_object.close()

with WriteToFile('test.txt') as f:
    f.write('Hello')

class AsyncSession:
    def __init__(self, url):
        """Принимет url"""
        self.url = url

    async def __aenter__(self):
        # Создаем объект сессии
        self.session = aiohttp.ClientSession()
        response = await self.session.get(self.url)
        return response

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        await self.session.close()

async def check(url):
    async with AsyncSession(url) as response:
        # Дожидаемся ответа и получаем его
        html = await response.text()
        print(f'{url}: {html[:20]}')

async def main():

    # Создаем Task
    # await asyncio.create_task(check('https://facebook.com'))
    res3 = asyncio.create_task(check('https://youtube.com'))
    res2 = asyncio.create_task(check('https://google.com'))
    res1 = asyncio.create_task(check('https://yandex.ru'))

    print(await res1)
    print(await res2)
    print(await res3)

if __name__ == '__main__':
    asyncio.run(main())


import psutil

def extract_process_info(process) -> (str, dict | str):
    """ returns tuple of name and extracted process data """
    try:
        process_name = process.name()
        process_data = {
            "pid": process.pid,
            "cpu_percent": process.cpu_percent(),
            "ram_memory_percent": process.memory_percent(),
        }
        return process_name, process_data
    except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess) as exception:
        return str(exception), "exception"

def get_processes_info():
    result = (extract_process_info(process) for process in psutil.process_iter())
    return dict(result)


# TO RUN: FLASK_APP=main.py FLASK_DEBUG=1 flask run

from flask import Flask, request, render_template, session, url_for, redirect
from flask_dropzone import Dropzone

import os

app = Flask(__name__)
dropzone = Dropzone(app)

# DROPZONE SETTINGS
app.config['DROPZONE_UPLOAD_MULTIPLE'] = True
app.config['DROPZONE_ALLOWED_FILE_CUSTOM'] = True
app.config['DROPZONE_ALLOWED_FILE_TYPE'] = 'image/*, .pdf, .doc, .txt'
app.config['DROPZONE_INVALID_FILE_TYPE']
app.config['DROPZONE_REDIRECT_VIEW'] = 'results' 	# redirect to results.html
app.config['DROPZONE_MAX_FILE_SIZE'] = 10
app.config['SECRET_KEY'] = 'secretkey'

# UPLOADS SETTINGS
app.config['UPLOADED_FILES_DEST'] = os.getcwd() + '/uploads'
# name of upload set, allowed extensions

from colour_vision import routes


import numpy as np
from recogym import build_agent_init, Configuration
from recogym.agents import (
    AbstractFeatureProvider,
    Model,
    ModelBasedAgent,
    ViewsFeaturesProvider
)

from sklearn.gaussian_process import GaussianProcessClassifier

model_sklearn_args = {
    # 'num_products': 100,
    'random_seed': np.random.randint(2 ** 31 - 1),
}

class GaussianProcessAgentModelBuilder(AbstractFeatureProvider):
    def __init__(self, config):
        super(GaussianProcessAgentModelBuilder, self).__init__(config)

    def build(self):
        class GaussianProcessAgentFeaturesProvider(ViewsFeaturesProvider):
            def __init__(self, config):
                super(GaussianProcessAgentFeaturesProvider, self).__init__(config)

            def features(self, observation):
                base_features = super().features(observation)
                return base_features.reshape(1, self.config.num_products)

        class GaussianProcessAgentModel(Model):
            def __init__(self, config, model):
                super(GaussianProcessAgentModel, self).__init__(config)
                self.model = model

            def act(self, observation, features):
                # X is a vector of organic counts
                X = features

                # We want a prediction for every action
                A = np.eye(P)

                # Get prediction for every action
                predictions = model.predict_proba(np.kron(X, A))[:, 1]

                # Take the one you think is most likely to give a click
                action = np.argmax(predictions)
                ps_all = np.zeros(self.config.num_products)
                ps_all[action] = 1.0

                return {
                    **super().act(observation, features),
                    **{
                        'a': action,
                        'ps': 1.0,
                        'ps-a': ps_all,
                    },
                }

        # Get data
        features, actions, deltas, pss = self.train_data()

        # Extract data properly
        X = features  # NxP vector where rows are users, columns are counts of organic views
        N = X.shape[0]  # Number of bandit feedback samples
        P = X.shape[1]  # Number of items
        A = actions  # Vector of length N - indicating the action that was taken
        y = deltas  # Vector of length N - indicating whether a click occurred

        # Explicitly build one-hot matrix for actions
        A_one_hot = np.zeros((N, P))
        A_one_hot[np.arange(N), A] = 1

        # TODO - this really doesn't scale, maybe sparsify?
        training_matrix = []

        for x, a in zip(X, A_one_hot):
            training_matrix.append(np.kron(x, a))

        training_matrix = np.asarray(training_matrix)

        np.savetxt('test.out', training_matrix, delimiter=',', fmt='%1f')

        '''
            random_state : int, RandomState instance or None, optional (default: None)
                The generator used to initialize the centers. If int,
                random_state is the seed used by the random number generator;
                If RandomState instance, random_state is the random number generator;
                If None, the random number generator is the RandomState instance used by np.random.

            multi_class : string, default
                Specifies how multi-class classification problems are handled.
                Supported are “one_vs_rest” and “one_vs_one”. In “one_vs_rest”,
                one binary Gaussian process classifier is fitted for each class,
                which is trained to separate this class from the rest.
                In “one_vs_one”, one binary Gaussian process classifier is fitted for each pair of classes,
                which is trained to separate these two classes.
                The predictions of these binary predictors are combined into multi-class predictions.
                Note that “one_vs_one” does not support predicting probability estimates.
                Default is "one_vs_rest"

        '''

        # Train a model
        model = GaussianProcessClassifier().fit(training_matrix, y)

        return (
            GaussianProcessAgentFeaturesProvider(self.config),
            GaussianProcessAgentModel(self.config, model)
        )

class GaussianProcessAgent(ModelBasedAgent):
    """
    Scikit-Learn-based SVM Agent.
    """

    def __init__(self, config=Configuration(model_sklearn_args)):
        super(GaussianProcessAgent, self).__init__(
            config,
            GaussianProcessAgentModelBuilder(config)
        )

agent = build_agent_init('GaussianProcessAgent',
                         GaussianProcessAgent,
                         {**model_sklearn_args})


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

from copy import deepcopy
from datetime import datetime
import os
from pprint import pprint

from dlstats.fetchers.insee import INSEE as Fetcher
from dlstats import constants

import unittest
from unittest import mock
import httpretty

from dlstats.tests.fetchers.base import BaseFetcherTestCase
from dlstats.tests.resources import xml_samples
from dlstats.tests.base import RESOURCES_DIR as BASE_RESOURCES_DIR

RESOURCES_DIR = os.path.abspath(os.path.join(BASE_RESOURCES_DIR, "insee"))

def get_dimensions_from_dsd(self, xml_dsd=None, provider_name=None, dataset_code=None, dsd_id=None):
    dimension_keys = ['FREQ', 'NATURE', 'PRODUIT']
    dimensions = {
        'FREQ': {'M': 'M'},
        'NATURE': {},
        'PRODUIT': {},
    }
    return dimension_keys, dimensions

def get_dimensions_from_dsd_CHO_AN_AGE(self, xml_dsd=None, provider_name=None, dataset_code=None, dsd_id=None):
    dimension_keys = ['INDICATEUR', 'SEXE', 'AGE']
    dimensions = {
        'INDICATEUR': {'Nbre': 'Nbre'},
        'SEXE': {},
        'AGE': {},
    }
    return dimension_keys, dimensions

LOCAL_DATASETS_UPDATE = {
    "IPI-2010-A21": {
        "categories_root": ['COMPTA-NAT', 'CONDITIONS-VIE-SOCIETE', 'DEMO-ENT',
                            'ECHANGES-EXT', 'ENQ-CONJ', 'MARCHE-TRAVAIL',
                            'POPULATION', 'PRIX', 'PRODUCTION-ENT',
                            'SALAIRES-REVENUS', 'SERVICES-TOURISME-TRANSPORT',
                            'SRGDP'],
        "concept_keys": ['base-per', 'decimals', 'embargo-time', 'freq', 'idbank', 'last-update', 'nature', 'obs-status', 'produit', 'ref-area', 'time-per-collect', 'title', 'unit-measure', 'unit-mult'],
        "codelist_keys": ['base-per', 'decimals', 'embargo-time', 'freq', 'idbank', 'last-update', 'nature', 'obs-status', 'produit', 'ref-area', 'time-per-collect', 'title', 'unit-measure', 'unit-mult'],
        "codelist_count": {
            "base-per": 0,
            "decimals": 0,
            "embargo-time": 0,
            "freq": 7,
            "idbank": 0,
            "last-update": 0,
            "nature": 25,
            "obs-status": 10,
            "produit": 30,
            "ref-area": 11,
            "time-per-collect": 7,
            "title": 0,
            "unit-measure": 123,
            "unit-mult": 0,
        },
        "dimension_keys": ['freq', 'produit', 'nature'],
        "dimension_count": {
            "freq": 7,
            "produit": 30,
            "nature": 25,
        },
        "attribute_keys": ['idbank', 'title', 'last-update', 'unit-measure', 'unit-mult', 'ref-area', 'decimals', 'base-per', 'time-per-collect', 'obs-status', 'embargo-time'],
        "attribute_count": {
            "idbank": 0,
            "title": 0,
            "last-update": 0,
            "unit-measure": 123,
            "unit-mult": 0,
            "ref-area": 11,
            "decimals": 0,
            "base-per": 0,
            "time-per-collect": 7,
            "obs-status": 10,
            "embargo-time": 0,
        },
    },
}

DSD_INSEE_CHO_AN_AGE = {
    "provider": "INSEE",
    "filepaths": deepcopy(xml_samples.DATA_INSEE_SPECIFIC["DSD"]["filepaths"]),
    "dataset_code": "CHO-AN-AGE",
    "dataset_name": "Unemployment according to the ILO standard (annual average) - By gender and age",
    "dsd_id": "CHO-AN-AGE",
    "dsd_ids": ["CHO-AN-AGE"],
    "dataflow_keys": ['CHO-AN-AGE'],
    "is_completed": True,
    "concept_keys": ['age', 'base-per', 'decimals', 'embargo-time', 'freq', 'idbank', 'indicateur', 'last-update', 'obs-status', 'ref-area', 'sexe', 'time-per-collect', 'title', 'unit-measure', 'unit-mult'],
    "codelist_keys": ['age', 'base-per', 'decimals', 'embargo-time', 'freq', 'idbank', 'indicateur', 'last-update', 'obs-status', 'ref-area', 'sexe', 'time-per-collect', 'title', 'unit-measure', 'unit-mult'],
    "codelist_count": {
        "age": 73,
        "base-per": 0,
        "decimals": 0,
        "embargo-time": 0,
        "freq": 7,
        "idbank": 0,
        "indicateur": 9,
        "last-update": 0,
        "obs-status": 10,
        "ref-area": 11,
        "sexe": 3,
        "time-per-collect": 7,
        "title": 0,
        "unit-measure": 123,
        "unit-mult": 0,
    },
    "dimension_keys": ['indicateur', 'sexe', 'age'],
    "dimension_count": {
        "indicateur": 9,
        "sexe": 3,
        "age": 73,
    },
    "attribute_keys": ['freq', 'idbank', 'title', 'last-update', 'unit-measure', 'unit-mult', 'ref-area', 'decimals', 'base-per', 'time-per-collect', 'obs-status', 'embargo-time'],
    "attribute_count": {
        "freq": 7,
        "idbank": 0,
        "title": 0,
        "last-update": 0,
        "unit-measure": 123,
        "unit-mult": 0,
        "ref-area": 11,
        "decimals": 0,
        "base-per": 0,
        "time-per-collect": 7,
        "obs-status": 10,
        "embargo-time": 0,
    },
}

DSD_INSEE_CHO_AN_AGE["filepaths"]["datastructure"] = os.path.abspath(os.path.join(RESOURCES_DIR, "insee-datastructure-CHO-AN-AGE.xml"))

DATA_INSEE_CHO_AN_AGE = {
    "filepath": os.path.abspath(os.path.join(RESOURCES_DIR, "insee-data-CHO-AN-AGE.xml")),
    "klass": "XMLSpecificData_2_1_INSEE",
    "DSD": DSD_INSEE_CHO_AN_AGE,
    "kwargs": {
        "provider_name": "INSEE",
        "dataset_code": "CHO-AN-AGE",
        "dsd_filepath": DSD_INSEE_CHO_AN_AGE["filepaths"]["datastructure"],
    },
    "series_accept": 31,
    "series_reject_frequency": 0,
    "series_reject_empty": 0,
    "series_all_values": 1219,
    "series_key_first": '001664976',
    "series_key_last": '001665006',
    "series_sample": {
        "provider_name": "INSEE",
        "dataset_code": "CHO-AN-AGE",
        'key': '001664976',
        'name': 'Number - Men - From 15 to 24 years old',
        'frequency': 'A',
        'last_update': None,
        'first_value': {
            'value': '143',
            'period': '1975',
            'attributes': {
                "OBS_STATUS": "A"
            },
        },
        'last_value': {
            'value': '359',
            'period': '2014',
            'attributes': {
                "OBS_STATUS": "A"
            },
        },
        'dimensions': {
           'INDICATEUR': 'Nbre',
           'SEXE': '1',
           'AGE': '15-24',
        },
        'attributes': {
            'DECIMALS': '0',
            'FREQ': 'A',
            'LAST_UPDATE': '2016-02-10',
            'REF_AREA': 'FM',
            'TIME_PER_COLLECT': 'MOYENNE',
            'TITLE': 'Nombre de chômeurs au sens du BIT (moyenne annuelle) - Hommes de 15 à 24 ans - France métropolitaine',
            'UNIT_MEASURE': 'IND',
            'UNIT_MULT': '3'
        },
    }
}

class FetcherTestCase(BaseFetcherTestCase):

    # nosetests -s -v dlstats.tests.fetchers.test_insee:FetcherTestCase

    FETCHER_KLASS = Fetcher
    DATASETS = {
        'IPI-2010-A21': deepcopy(xml_samples.DATA_INSEE_SPECIFIC),
        'CHO-AN-AGE': DATA_INSEE_CHO_AN_AGE
    }
    DATASET_FIRST = "ACT-TRIM-ANC"
    DATASET_LAST = "TXEMP-AN-FR"
    DEBUG_MODE = False

    def _load_files(self, dataset_code, data_key=None):

        filepaths = self.DATASETS[dataset_code]["DSD"]["filepaths"]
        dsd_content_type = 'application/vnd.sdmx.structure+xml;version=2.1'

        url = "http://www.bdm.insee.fr/series/sdmx/dataflow/INSEE"
        self.register_url(url,
                          filepaths["dataflow"],
                          content_type=dsd_content_type,
                          match_querystring=True)

        url = "http://www.bdm.insee.fr/series/sdmx/categoryscheme/INSEE"
        self.register_url(url,
                          filepaths["categoryscheme"],
                          content_type=dsd_content_type,
                          match_querystring=True)

        url = "http://www.bdm.insee.fr/series/sdmx/categorisation/INSEE"
        self.register_url(url,
                          filepaths["categorisation"],
                          content_type=dsd_content_type,
                          match_querystring=True)

        url = "http://www.bdm.insee.fr/series/sdmx/conceptscheme/INSEE"
        self.register_url(url,
                          filepaths["conceptscheme"],
                          content_type=dsd_content_type,
                          match_querystring=True)

        for cl in ["CL_UNIT", "CL_AREA", "CL_TIME_COLLECT", "CL_OBS_STATUS", "CL_UNIT_MULT", "CL_FREQ"]:
            url = "http://www.bdm.insee.fr/series/sdmx/codelist/INSEE/%s" % cl
            self.register_url(url,
                              filepaths[cl],
                              content_type=dsd_content_type,
                              match_querystring=True)

        url = "http://www.bdm.insee.fr/series/sdmx/datastructure/INSEE/%s?reference=children" % dataset_code
        self.register_url(url,
                          filepaths["datastructure"],
                          content_type=dsd_content_type,
                          match_querystring=True)

        if data_key:
            url = "http://www.bdm.insee.fr/series/sdmx/data/%s/%s" % (dataset_code, data_key)
            self.register_url(url,
                              self.DATASETS[dataset_code]['filepath'],
                              content_type='application/vnd.sdmx.structurespecificdata+xml;version=2.1',
                              match_querystring=True)

    @httpretty.activate
    @unittest.skipUnless('FULL_TEST' in os.environ, "Skip - no full test")
    def test_load_datasets_first(self):

        dataset_code = 'IPI-2010-A21'
        self._load_files(dataset_code)
        self.assertLoadDatasetsFirst([dataset_code])

    @httpretty.activate
    @unittest.skipUnless('FULL_TEST' in os.environ, "Skip - no full test")
    def test_load_datasets_update(self):

        dataset_code = 'IPI-2010-A21'
        self._load_files(dataset_code)
        self.assertLoadDatasetsUpdate([dataset_code])

    @httpretty.activate
    def test_build_data_tree(self):

        # nosetests -s -v dlstats.tests.fetchers.test_insee:FetcherTestCase.test_build_data_tree

        dataset_code = 'IPI-2010-A21'
        self._load_files(dataset_code)
        self.DATASETS[dataset_code]["DSD"].update(LOCAL_DATASETS_UPDATE[dataset_code])
        self.assertDataTree(dataset_code)

    @httpretty.activate
    @mock.patch('dlstats.fetchers.insee.INSEE_Data._get_dimensions_from_dsd', get_dimensions_from_dsd)
    def test_upsert_dataset_ipi_2010_a21(self):

        # nosetests -s -v dlstats.tests.fetchers.test_insee:FetcherTestCase.test_upsert_dataset_ipi_2010_a21

        dataset_code = 'IPI-2010-A21'
        self.DATASETS[dataset_code]["DSD"].update(LOCAL_DATASETS_UPDATE[dataset_code])
        self.DATASETS[dataset_code]["series_sample"]["attributes"].pop("IDBANK", None)
        self._load_files(dataset_code, data_key="M..")
        self.assertProvider()
        dataset = self.assertDataset(dataset_code)
        series_list = self.assertSeries(dataset_code)

        self.assertTrue(dataset["last_update"] >= datetime(2016, 1, 8))

        self.assertEquals(series_list[0]["last_update_ds"], datetime(2016, 1, 8))
        self.assertEquals(series_list[-1]["last_update_ds"], datetime(2013, 3, 11))

    @httpretty.activate
    @mock.patch('dlstats.fetchers.insee.INSEE_Data._get_dimensions_from_dsd', get_dimensions_from_dsd_CHO_AN_AGE)
    def test_upsert_dataset_cho_an_age(self):

        # nosetests -s -v dlstats.tests.fetchers.test_insee:FetcherTestCase.test_upsert_dataset_cho_an_age

        dataset_code = 'CHO-AN-AGE'
        self._load_files(dataset_code, data_key="Nbre..")
        self.assertProvider()
        dataset = self.assertDataset(dataset_code)
        series_list = self.assertSeries(dataset_code)

        self.assertTrue(dataset["last_update"] >= datetime(2016, 2, 10))

        self.assertEquals(series_list[0]["last_update_ds"], datetime(2016, 2, 10))
        self.assertEquals(series_list[-1]["last_update_ds"], datetime(2016, 2, 12))

    @httpretty.activate
    @unittest.skipIf(True, "TODO")
    def test_is_updated(self):

        # nosetests -s -v dlstats.tests.fetchers.test_insee:FetcherTestCase.test_is_updated
        """
        use dataset.series.now
        """

        dataset_code = 'IPI-2010-A21'

        self._load_files(dataset_code)
        self.insee.upsert_dataset(dataset_code)

        '''series avec un LAST_UPDATE > au dataset'''
        query = {
            'provider_name': self.insee.provider_name,
            "dataset_code": dataset_code
        }
        new_datetime = datetime(2015, 12, 9)
        result = self.db[constants.COL_DATASETS].update_one(query, {"$set": {'last_update': new_datetime}})
        pprint(result.raw_result)
        self._load_files(dataset_code)
        self.insee.upsert_dataset(dataset_code)
        _series = self.insee.insee_data._series
        #pprint(_series)
        for s in _series:
            print(s['key'])
        d = self.db[constants.COL_DATASETS].find_one(query)
        print("dataset : ", d['last_update'])
        self.assertEqual(len(_series), 11)


import numpy as np
import torch
import random
import copy
import glob
import os

def flatten(t):
    return [item for sublist in t for item in sublist]

def get_positions_distances_mat(length, negative=False):
    '''
    For length 4:
    distance matrix = [[1,2,3,4],[2,1,2,3],[3,2,1,2],[4,3,2,1]]
    '''

    distances_matrix = np.zeros((length,length))
    tri = flatten([list(np.arange(i)+1) for i in range(length-1,0,-1)])
    distances_matrix[np.triu_indices(length,1)] = tri
    if not negative:
        distances_matrix += distances_matrix.T
    else:
        distances_matrix -= distances_matrix.T

    if not negative:
        return torch.tensor(distances_matrix)# + 1
    else:
        return torch.tensor(distances_matrix)

def calc_global_metric(attn_mat):
    '''
    Calculate a metric to estimate how much a given attntion head is global in thier weights.
    For a given head, the calculation is a mean weighted sum for every token.
    The score for token in position i = sum_{for every token in position j}(a/num_of_tokens)

    A score of 1.0 is completely global, a score of 1/num_of_tokens is completely local.
    '''

    cur_max_position = attn_mat.shape[-1] # maximal number of tokens
    distances_matrix = get_positions_distances_mat(cur_max_position).to(attn_mat.device) # global weights, the higher the more global

    # normlize weights to sum to 1.0, in case they don't (in remove EOS)
    norm_attn_mat = attn_mat / attn_mat.sum(dim=1).unsqueeze(1).expand(attn_mat.shape)

    sum_mat = torch.sum(distances_matrix*norm_attn_mat,axis=len(norm_attn_mat.shape)-1)
    normalized_weight_distanced = sum_mat / (cur_max_position + 1) # normlize score according to length so max is 1

    return normalized_weight_distanced.mean(-1)

def weighted_median(data, weights):
    """
    Args:
      data (list or numpy.array): data
      weights (list or numpy.array): weights

    returns the weighted median in data according to weights (float)
    """
    data, weights = np.array(data).squeeze(), np.array(weights).squeeze()
    s_data, s_weights = map(np.array, zip(*sorted(zip(data, weights))))
    midpoint = 0.5 * sum(s_weights)
    if any(weights > midpoint):
        w_median = (data[weights == np.max(weights)])[0]
    else:
        cs_weights = np.cumsum(s_weights)
        idx = np.where(cs_weights <= midpoint)[0][-1]
        if cs_weights[idx] == midpoint:
            w_median = np.mean(s_data[idx:idx+2])
        else:
            w_median = s_data[idx+1]
    return w_median

def get_mean_distance_weighted_median(attn_mat):
    num_of_tokens = attn_mat.shape[0]
    dists = get_positions_distances_mat(num_of_tokens,negative=True)
    #sum_of_weighted_medians = 0
    all_weighted_medians = []
    for index_token in range(num_of_tokens):
        cur_weighted_median = weighted_median(dists[index_token], attn_mat[index_token]/sum(attn_mat[index_token])) # scale weights to sum to 1.0 if they are not (in remove EOS)
        # sum_of_weighted_medians += abs(cur_weighted_median)
        all_weighted_medians.append(abs(cur_weighted_median))
    return np.percentile(all_weighted_medians, 90)

def get_model_wmd_gloablity_scores(attn_mat, LENGTH, NUM_LAYERS, NUM_HEADS, with_eos=True):
    distance_weighted_median = []
    globality_scores = []
    for i in range(NUM_LAYERS):
        for j in range(NUM_HEADS):
            cur_head = attn_mat[i][j][:LENGTH,:LENGTH]
            if not with_eos:
                cur_head = cur_head[:-1,:-1]
            distance_weighted_median.append(get_mean_distance_weighted_median(cur_head))
            globality_scores.append(calc_global_metric(cur_head).item())

    model_distance_weighted_median = sum(distance_weighted_median)/len(distance_weighted_median)
    model_globality_scores = sum(globality_scores)/len(globality_scores)
    return model_globality_scores, model_distance_weighted_median

def get_all_samples_globality_and_wmd(model_attn_dir, NUM_SAMPLES, NUM_LAYERS, NUM_HEADS, lengths_dict, with_eos):
    all_g, all_w = [], []

    for sample_num in range(NUM_SAMPLES):
        sample_attn_matrix = get_sample_attn_matrix_load(sample_num, model_attn_dir)
        length = get_sample_len(sample_num, model_attn_dir, NUM_SAMPLES)
        g, w = get_model_wmd_gloablity_scores(sample_attn_matrix, length, NUM_LAYERS, NUM_HEADS, with_eos=with_eos)
        all_g.append(g)
        all_w.append(w)
    return all_g, all_w


import argparse
from argparse import RawTextHelpFormatter
import json

def main():
    parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter)
    parser.add_argument('output',
                        type=str,
                        help='Output file name')
    parser.add_argument('--seg_model',
                        type=str,
                        help='Path to a model parameter file (.pth).',
                        required=True)
    parser.add_argument('--device',
                        type=str,
                        help='\"cpu\" or \"cuda\".\ndefault: \"cuda\"',
                        default='cuda')
    parser.add_argument('--scales',
                        metavar='size',
                        type=float,
                        nargs='+',
                        help=(
                            'Pixel/voxels sizes in physical scale in the ' +
                            'order of [X, Y(, Z)].'),
                        required=True)
    parser.add_argument('--c_ratio',
                        type=float,
                        help=(
                            'Center ratio used to recover ellipses/ellipsoids' +
                            ' from center prediction (generally it should be ' +
                            'the same value as used in ' +
                            'prep/generate_generate_seg_labels.py.\n' +
                            'default: 0.3'
                        ),
                        default=0.3)
    parser.add_argument('--p_thresh',
                        type=float,
                        help=(
                            'Probability threshold for prediction. Pixels with ' +
                            'a central probability higher than this value are ' +
                            'subject to further processing.\ndefault: 0.5'
                        ),
                        default=0.5)
    parser.add_argument('--r_min',
                        type=float,
                        help=(
                            'Minimum threshold of radii of detections in ' +
                            'physical scale. If at least one of the radii of' +
                            'a detection is smaller than this value, the ' +
                            'detection is discarded.\ndefault: 0'
                        ),
                        default=0)
    parser.add_argument('--r_max',
                        type=float,
                        help=(
                            'Maximum threshold of radii of detections in ' +
                            'physical scale. The radii of a detection larger ' +
                            'than r_max become r_max.\ndefault: 1e6'
                        ),
                        default=1e6)
    parser.add_argument('--is_3d',
                        help=('Specify if data is 3D.'),
                        action='store_true')
    parser.add_argument('--use_interpolation',
                        help=(
                            'Specify if interpolation of missing spots is ' +
                            'turned on.'
                        ),
                        action='store_true')
    parser.add_argument('--linking_threshold',
                        type=float,
                        help=(
                            'Threshold value for linking in physical scale.\n' +
                            'Links with smaller values than this value are ' +
                            'accepted.\ndefault: 5.0'
                        ),
                        default=5.0)
    parser.add_argument('--search_depth',
                        type=int,
                        help=(
                            'The linking algorithm tries to find the parent ' +
                            'spot up to the current timepoint - search_depth.' +
                            '\ndefault: 3'
                        ),
                        default=3)
    parser.add_argument('--search_neighbors',
                        type=int,
                        help=(
                            'The linking algorithm tries to find the parent ' +
                            'spot up to search_neighbors in the target ' +
                            'timepoint.\ndefault: 3'
                        ),
                        default=3)
    parser.add_argument('--max_edges',
                        type=int,
                        help=(
                            'The linking algorithm accepts max_edges links ' +
                            'at maximum for each parent spot.\ndefault: 1'
                        ),
                        default=1)
    parser.add_argument('--division_min_displacement',
                        type=float,
                        help=(
                            'This value is combined with ' +
                            'division_acceptable_distance to determin if a ' +
                            'spot is dividing.\ndefault: 1.0'
                        ),
                        default=1.0)
    parser.add_argument('--division_acceptable_distance',
                        type=float,
                        help=(
                            'This value is combined with ' +
                            'division_min_displacement to determin if a ' +
                            'spot is dividing.\ndefault: 1.0'
                        ),
                        default=1.0)
    parser.add_argument('--dryrun',
                        help=('Print output to the console instead of a file.'),
                        action='store_true')
    args = parser.parse_args()
    if args.device not in ('cpu', 'cuda'):
        raise ValueError('--device should be \"cpu\" or \"cuda\"')
    if len(args.scales) != 2 + args.is_3d:
        raise ValueError(f'--scales should have the length {2 + args.is_3d}')
    if not 0 <= args.c_ratio <= 1:
        raise ValueError('--c_ratio should be in the range [0, 1]')
    if not 0 <= args.p_thresh <= 1:
        raise ValueError('--p_thresh should be in the range [0, 1]')
    if args.r_min < 0:
        raise ValueError('--r_min should not be a negative value')
    if args.r_max < 0:
        raise ValueError('--r_max should not be a negative value')
    if args.r_max < args.r_min:
        raise ValueError('--r_max should be equal or greater than r_min')
    if args.linking_threshold < 0:
        raise ValueError('--linking_threshold should not be a negative value')
    if args.search_depth < 1:
        raise ValueError('--search_depth should be a positive value')
    if args.search_neighbors < 1:
        raise ValueError('--search_neighbors should be a positive value')
    if args.max_edges < 1:
        raise ValueError('--max_edges should be a positive value')
    if args.division_min_displacement < 0:
        raise ValueError(
            '--division_min_displacement should not be a negative value'
        )
    if args.division_acceptable_distance < 0:
        raise ValueError(
            '--division_acceptable_distance should not be a negative value'
        )
    config_dict = vars(args).copy()
    config_dict.pop('output')
    config_dict.pop('dryrun')
    config_dict['use_2d'] = True
    config_dict['is_pad'] = True
    config_dict['use_opticalflow'] = False
    if args.dryrun:
        print(json.dumps(config_dict, indent=4))
    else:
        with open(args.output, "w") as outfile:
            json.dump(config_dict, outfile, indent=4)

if __name__ == '__main__':
    main()


from datetime import date

pessoa = {'Nome': input('Digite seu nome: ').strip().title(),
          'Ano de nascimento': int(input('Digite o ano de seu nascimento: ')),
          'CTPS': input('Digite sua CTPS: ').strip()}

pessoa['Idade'] = date.today().year - pessoa['Ano de nascimento']
del pessoa['Ano de nascimento']

if pessoa['CTPS'] != 0:
    pessoa['Ano de contratação'] = int(input('Digite o ano da sua contratação: '))
    pessoa['Salário'] = float(input('Digite seu salário: '))

    print('_' * 50)
    print(f'Nome do(a) contribuinte: {pessoa["Nome"]}')
    print(f'Idade do(a) contribuinte: {pessoa["Idade"]}')
    print(f'Se aposentará com {pessoa["Idade"] + 35} anos')
    print(f'Seu CTPS é {pessoa["CTPS"]} e ganha R${pessoa["Salário"]:.2f}')


from ..layers.basic import EqualisedConvLayer, EqualisedLinearLayer, get_activ, get_norm, get_padding, spectral_norm, is_affine
from ..layers.normalization import InstanceNorm2d
import numpy as np
import torch.nn as nn
import torch.nn.functional as F
import transformers
import torch

class tRGB(nn.Module):
    def __init__(self, ic):
        super().__init__()
        self._transform = nn.Sequential(*[
            SpectralDecoupledConv(ic, 3, ks=3),
            nn.Tanh()
        ])

    def forward(self, x):
        return self._transform(x)

class SpectralDecoupledConv(nn.Module):
    def __init__(self, ic, oc, ks=3, s=1, d=1, bias=True, use_pad=True):
        super().__init__()
        self.stride = s
        self.dilation = d
        if use_pad:
            self.pad_size = int(np.ceil((ks - 1.0) / 2))
        else:
            self.pad_size = 0
        self._conv = spectral_norm(nn.Conv2d(ic, oc, ks, s, padding=self.pad_size, dilation=d, bias=bias))

    def get_bias(self):
        return self._conv.bias.view(1, -1, 1, 1)

    def forward(self, x, add_bias=True):
        #if add_bias:
        #    bias = self._conv.bias
        #    if bias is not None:
        #        return F.conv2d(x, self._conv.weight_orig, bias, stride=self.stride, dilation=self.dilation, padding=self.pad_size)
        #else:
        #    # return self._conv(x)
        #    return F.conv2d(x, self._conv.weight_orig, None, stride=self.stride, dilation=self.dilation, padding=self.pad_size)
        return self._conv(x)

class SpectralLinear(nn.Module):
    def __init__(self, dim_in, dim_out, bias=True):
        super().__init__()
        self._linear = spectral_norm(nn.Linear(dim_in, dim_out, bias=bias))

    def forward(self, x):
        out = self._linear(x)
        return out

class SpectralWrapperNorm(nn.Module):
    def __init__(self, constructor, num_features):
        super().__init__()
        self._norm = spectral_norm(constructor(num_features))

    def forward(self, x):
        return self._norm(x)

class SpectralAdaptiveNorm(nn.Module):
    def __init__(self, dim_in, dim_out):
        super().__init__()
        self.std_layer = SpectralLinear(dim_in, dim_out)
        self.mean_layer = SpectralLinear(dim_in, dim_out)
        self.sequential_test = nn.Sequential()

    def forward(self, features, x):
        s_mean = self.mean_layer(features)
        s_std = self.std_layer(features)

        size = x.size()
        x = x.view(size[0], size[1], size[2] * size[3])
        mean = x.mean(2, keepdim=True)
        x = x - mean
        std = torch.rsqrt((x ** 2).mean(2, keepdim=True) + 1e-8)
        norm_features = (x * std).view(*size)
        output = norm_features * s_std.unsqueeze(-1).unsqueeze(-1) + s_mean.unsqueeze(-1).unsqueeze(-1)
        return output

class NoiseLayer(nn.Module):
    def __init__(self, num_channels):
        super().__init__()
        self.weight = nn.Parameter(torch.zeros(num_channels))
        self.noise = None

    def forward(self, x, noise=None):
        if self.noise == None and noise == None:
            noise = torch.rand(size=(x.size(0), 1, x.size(2), x.size(3)), device=x.device, dtype=x.dtype)
        elif noise == None:
            noise = self.noise
        out = x + noise * self.weight.view(1, -1, 1, 1)
        return out

class SpectralWeights(nn.Module):
    def __init__(self, num_channels):
        super().__init__()
        self.weight = nn.Parameter(torch.zeros(num_channels))

    def forward(self, x):
        pass

class SpectralNoiseLayer(nn.Module):
    def __init__(self, num_channels):
        super().__init__()
        self._layer = spectral_norm(SpectralWeights(num_channels))
        self.noise = None

    def forward(self, x, noise=None):
        if self.noise == None and noise == None:
            noise = torch.rand(size=(x.size(0), 1, x.size(2), x.size(3)), device=x.device, dtype=x.dtype)
        elif noise == None:
            noise = self.noise
        out = x + noise * self._layer.weight_orig.view(1, -1, 1, 1)
        return out

class StyleNetwork(nn.Module):
    def __init__(self, cfg):
        super().__init__()
        global style_scales
        self.input_dim = cfg.latent_dim
        self._proj_dim = cfg.style_dim

        _style_net = [SpectralLinear(self.input_dim, self._proj_dim),
                      #nn.LeakyReLU(negative_slope=0.2),
                      # nn.BatchNorm1d(self._proj_dim)
                      ]
        for _ in range(cfg.style_layers):
            _style_net += [SpectralLinear(self._proj_dim, self._proj_dim),
                           #nn.LeakyReLU(negative_slope=0.2),
                           # nn.BatchNorm1d(self._proj_dim)
                           ]
        self._style_net = nn.Sequential(*_style_net)

    def forward(self, x):
        style = self._style_net(x)
        return style

class StyleBlock(nn.Module):
    def __init__(self, cfg, ic, oc, ks=3, pad='reflect', act='leaky_relu', upsample=False):
        global style_scales
        super().__init__()

        pad_size = int(np.ceil((ks - 1.0) / 2))
        self.act = get_activ(act)()
        # self.pad = get_padding(pad)(pad_size)

        self.k = min(ic, oc)
        self._conv_1 = SpectralDecoupledConv(ic, self.k, ks, bias=True)
        self._style_1 = SpectralAdaptiveNorm(cfg.style_dim, self.k)
        self._noise_1 = SpectralNoiseLayer(self.k)

        self._conv_2 = SpectralDecoupledConv(self.k, oc, ks, bias=True)
        self._style_2 = SpectralAdaptiveNorm(cfg.style_dim, oc)
        self._noise_2 = SpectralNoiseLayer(oc)

        if upsample:
            self.upsample = nn.Upsample(scale_factor=2, mode='bilinear')
        else:
            self.upsample = None

    def forward(self, input, style):
        if isinstance(input, tuple):
            in_feat, _ = input
        else:
            in_feat = input
        if self.upsample:
            x = self.upsample(in_feat)
        else:
            x = in_feat
        # feat = self.pad(x)
        feat = x
        feat = self._conv_1(feat, add_bias=False)
        feat = self.act(feat)
        feat = self._style_1(style, feat)
        feat = self._noise_1(feat) + self._conv_1.get_bias()
        # feat = self.pad(feat)
        feat = self._conv_2(feat, add_bias=False)
        feat = self.act(feat)
        feat = self._style_2(style, feat)
        feat = self._noise_2(feat) + self._conv_2.get_bias()
        return feat, x

class StyleGenerator(nn.Module):
    def __init__(self, cfg):
        super().__init__()
        global style_scales
        style_scales = []
        self.cfg = cfg
        self.latent_scale = int(cfg.load_size // (2 ** 6))
        self.latent_channels = int(cfg.latent_dim) // (self.latent_scale ** 2)
        self._learn_channels = 16 * cfg.ngf - self.latent_channels
        self._const_init = torch.nn.Parameter(torch.rand(size=(self._learn_channels, self.latent_scale, self.latent_scale)))
        self.upsample = nn.Upsample(scale_factor=2, mode='bilinear')

        _init_layers = []
        for _ in range(1):
            _init_layers += [StyleBlock(cfg, 16 * cfg.ngf, 16 * cfg.ngf, upsample=True)]
        _init_layers += [StyleBlock(cfg, 16 * cfg.ngf, 16 * cfg.ngf, upsample=True)]
        _init_layers += [StyleBlock(cfg, 16 * cfg.ngf, 16 * cfg.ngf, upsample=True)]
        _init_layers += [StyleBlock(cfg, 16 * cfg.ngf, 16 * cfg.ngf, upsample=False)]
        self._init_layers = nn.ModuleList(_init_layers)

        generator_bodies = []
        generator_bodies.append(nn.ModuleList([StyleBlock(cfg, cfg.ngf * 16, cfg.ngf * 8, upsample=True),
                                               StyleBlock(cfg, cfg.ngf * 8, cfg.ngf * 8, upsample=False)]))
        generator_bodies.append(nn.ModuleList([StyleBlock(cfg, cfg.ngf * 8, cfg.ngf * 4, upsample=True),
                                               StyleBlock(cfg, cfg.ngf * 4, cfg.ngf * 4, upsample=False)]))
        generator_bodies.append(nn.ModuleList([StyleBlock(cfg, cfg.ngf * 4, cfg.ngf * 2, upsample=True),
                                               StyleBlock(cfg, cfg.ngf * 2, cfg.ngf * 2, upsample=False)]))
        self.generator_bodies = nn.ModuleList(generator_bodies)
        self.generator_heads = nn.ModuleList([tRGB(cfg.ngf * f) for f in [8, 4, 2]])
        self.style_network = StyleNetwork(cfg)

    def forward(self, input_style, input_content):
        content = input_content.view(input_content.size(0), self.latent_channels, self.latent_scale, self.latent_scale)
        const = self._const_init.repeat(input_content.size(0), 1, 1, 1)
        feats = torch.cat([content, const], dim=1)
        style = self.style_network(input_style)
        for _layer in self._init_layers:
            feats = _layer(feats, style)

        # TODO: add style mixing for v9 (randomly sample between a style, and interpolated style)
        # TODO: should do something with those noise, layers as well
        # TODO: for style mixing, use fixed noisem
        results = []
        for _layers, _head in zip(self.generator_bodies, self.generator_heads):
            for _l in _layers:
                feats, _ = _l(feats, style)
            results += [_head(feats)]
        return results