from kafka import KafkaProducer
import csv
from time import sleep
import json
import concurrent.futures
from concurrent.futures import ThreadPoolExecutor

# Kafka broker address
bootstrap_servers = '10.18.17.153:9092'
# Kafka topics to send the data
topic_LF = "Heelstrike_LF"
topic_LH = "Heelstrike_LH"
topic_LS = "Heelstrike_LS"
topic_RF = "Heelstrike_RF"
topic_RH = "Heelstrike_RH"
topic_RS = "Heelstrike_RS"
topic_SA = "Heelstrike_SA"

# Create a Kafka producer
producer = KafkaProducer(bootstrap_servers=bootstrap_servers,
                         value_serializer=lambda v: json.dumps(v).encode('utf-8'))

# Load the CSV files into DataFrames
csv_file_LF = "/home/ayemon/KafkaProjects/kafkaspark07_90/heelstrike/heelstrike_10/LF_all_10.csv"
csv_file_LH = "/home/ayemon/KafkaProjects/kafkaspark07_90/heelstrike/heelstrike_10/LH_all_10.csv"
csv_file_LS = "/home/ayemon/KafkaProjects/kafkaspark07_90/heelstrike/heelstrike_10/LS_all_10.csv"
csv_file_RF = "/home/ayemon/KafkaProjects/kafkaspark07_90/heelstrike/heelstrike_10/RF_all_10.csv"
csv_file_RH = "/home/ayemon/KafkaProjects/kafkaspark07_90/heelstrike/heelstrike_10/RH_all_10.csv"
csv_file_RS = "/home/ayemon/KafkaProjects/kafkaspark07_90/heelstrike/heelstrike_10/RS_all_10.csv"
csv_file_SA = "/home/ayemon/KafkaProjects/kafkaspark07_90/heelstrike/heelstrike_10/SA_all_10.csv"

def send_csv_to_kafka_with_label(csv_file, topic):
    with open(csv_file, 'r') as file:
        csv_reader = csv.reader(file)
        header = next(csv_reader)  # Get the header
        for row in csv_reader:
            # Assuming each row is a list of numerical values
            message = dict(zip(header, row))
            producer.send(topic, value=message)
            print(f"Sending data to topic '{topic}': {message}")
            sleep(2)

if __name__ == "__main__":
    with ThreadPoolExecutor(max_workers=7) as executor:
        future1 = executor.submit(send_csv_to_kafka_with_label, csv_file_LF, topic_LF)
        future2 = executor.submit(send_csv_to_kafka_with_label, csv_file_LH, topic_LH)
        future3 = executor.submit(send_csv_to_kafka_with_label, csv_file_LS, topic_LS)
        future4 = executor.submit(send_csv_to_kafka_with_label, csv_file_RF, topic_RF)
        future5 = executor.submit(send_csv_to_kafka_with_label, csv_file_RH, topic_RH)
        future6 = executor.submit(send_csv_to_kafka_with_label, csv_file_RS, topic_RS)
        future7 = executor.submit(send_csv_to_kafka_with_label, csv_file_SA, topic_SA)

        # Wait for both tasks to complete
        concurrent.futures.wait([future1, future2, future3, future4, future5, future6, future7])

    producer.close()


from logging import raiseExceptions
import numpy as np
from gym.utils import seeding
import gym
from gym import spaces
import pandas as pd
import argparse

parser = argparse.ArgumentParser()
# notice that although the title contains OE, the state does not contain any information about order
# but traditional OHLCV like algorithm trading
# the key difference of this OE and algorithm trading is that it can only put action at one side, i.e. if
#the OE task is asked to buy one share of BTC, you can not put ask order even you still have BTC in your hand
# therefore, we use the dataset of BTC algorithm trading yet the env is a little different.
# in oe, we want to sell at the highest or buy at the lowest, therefore the optimization target is set to be
# the amount of money we sell, if the target is buying, our target will be nagative, they will both be optimized
# to their max
# all of the trades will be conducted at their close price
# this give me a little bit confusion about the sparation way of dataset, because it is not like the
#discrete action space where we can adjust the target amount with portion to the that of a train dataset
# and the valid dataset, which might cause a problem. Here to be more speicifcally
parser.add_argument(
    "--df_path",
    type=str,
    default="data/data/BTC/valid.csv",
    help="the path for the downloaded data to generate the environment")
parser.add_argument("--tech_indicator_list",
                    type=list,
                    default=[
                        "high", "low", "open", "close", "adjcp", "zopen",
                        "zhigh", "zlow", "zadjcp", "zclose", "zd_5", "zd_10",
                        "zd_15", "zd_20", "zd_25", "zd_30"
                    ],
                    help="the name of the features to predict the label")
parser.add_argument("--sell_target",
                    type=int,
                    default=1,
                    choices=[-1, 1],
                    help="1 for sell and -1 for buy")
parser.add_argument("--num_back_day",
                    type=int,
                    default=10,
                    help="number of backwards day")

class TradingEnv(gym.Env):
    def __init__(self, config):
        #init
        self.tech_indicator_list = config["tech_indicator_list"]
        self.df = pd.read_csv(config["df_path"], index_col=0)
        self.action_target = config["sell_target"]
        self.backward_num_day = config["num_back_day"]
        self.action_space = spaces.Box(
            low=0,
            high=1,
            shape=(1, ),
        )
        self.observation_space = spaces.Box(
            low=-np.inf,
            high=np.inf,
            shape=(self.backward_num_day, len(self.tech_indicator_list)),
        )
        # reset

        # the compound_memory's element consists of 2 parts: the cash and the number of bitcoin you have in hand

        self.day = self.backward_num_day
        self.data_public_imperfect = self.df.iloc[
            self.day - self.backward_num_day:self.day, :]
        self.data_public_perfect = self.df.iloc[
            self.day - self.backward_num_day:self.day +
            self.backward_num_day, :]
        self.public_imperfect_state = [
            self.data_public_imperfect[
                self.tech_indicator_list].values.tolist()
        ]
        self.public_perfect_state = [
            self.data_public_perfect[self.tech_indicator_list].values.tolist()
        ]
        # private state indicates the left date and order
        self.private_state = np.array([1, 1])
        self.terminal = False
        self.money_sold = 0
        self.private_state_list = [self.private_state] * self.backward_num_day

    def reset(self):
        self.terminal = False
        self.day = self.backward_num_day
        self.data_public_imperfect = self.df.iloc[
            self.day - self.backward_num_day:self.day, :]
        self.data_public_perfect = self.df.iloc[
            self.day - self.backward_num_day:self.day +
            self.backward_num_day, :]
        self.public_imperfect_state = [
            self.data_public_imperfect[
                self.tech_indicator_list].values.tolist()
        ]
        self.public_perfect_state = [
            self.data_public_perfect[self.tech_indicator_list].values.tolist()
        ]
        # private state indicates the
        self.private_state = np.array([1, 1])
        self.money_sold = 0
        self.private_state_list = [self.private_state] * self.backward_num_day
        return np.array(self.public_imperfect_state), {
            "perfect_state": np.array(self.public_perfect_state),
            "private_state": np.array([self.private_state_list])
        }

    def step(self, action):
        # based on the current price information, we decided whether to trade use the next day's price
        # the reward is calculated as at*(p_(t+1)-average(p))
        self.day = self.day + 1

        self.terminal = (self.day >= (len(self.df) - self.backward_num_day))
        if self.terminal:
            leftover_day, leftover_order = self.private_state
            print("done")
            self.data_public_imperfect = self.df.iloc[
                self.day - self.backward_num_day:self.day, :]
            current_price = self.data_public_imperfect.iloc[-1].close
            self.money_sold += leftover_order * current_price
            self.public_imperfect_state = np.array(self.public_imperfect_state)
            self.private_state_list.append([0, 0])
            self.private_state_list.remove(self.private_state_list[0])

            return self.public_imperfect_state, self.reward, self.terminal, {
                "perfect_state": np.array([self.public_perfect_state]),
                "private_state": np.array([self.private_state_list])
            }

        else:
            leftover_day, leftover_order = self.private_state

            previous_average_price = np.mean(self.df.iloc[:self.day -
                                                          1].close.values)
            self.data_public_imperfect = self.df.iloc[
                self.day - self.backward_num_day:self.day, :]
            self.data_public_perfect = self.df.iloc[
                self.day - self.backward_num_day:self.day +
                self.backward_num_day, :]
            self.public_imperfect_state = self.data_public_imperfect[
                self.tech_indicator_list].values.tolist()

            self.public_perfect_state = self.data_public_perfect[
                self.tech_indicator_list].values.tolist()

            self.public_imperfect_state = np.array(
                [self.public_imperfect_state])
            current_price = self.data_public_imperfect.iloc[-1].close
            if np.abs(action) < np.abs(leftover_order):
                self.money_sold += action * current_price
                self.reward = action * (
                    current_price / previous_average_price - 1)
            else:
                self.money_sold += leftover_order * current_price
                self.terminal = True
                print("done")
            leftover_day, leftover_order = leftover_day - 1 / (len(
                self.df) - 2 * self.backward_num_day), leftover_order - action
            self.private_state = np.array([leftover_day, leftover_order])
            self.private_state_list.append(self.private_state)
            self.private_state_list.remove(self.private_state_list[0])
            return self.public_imperfect_state, self.reward, self.terminal, {
                "perfect_state": np.array([self.public_perfect_state]),
                "private_state": np.array([self.private_state_list])
            }

    def find_money_sold(self):
        return self.money_sold

if __name__ == "__main__":
    args = parser.parse_args()
    config = vars(args)
    env = TradingEnv(config)
    print(env.observation_space.shape)
    _, info = env.reset()
    print(info["private_state"].shape)
    # action = 0.00001
    # done = False
    # i = 0
    # while not done:
    #     s, r, done, info = env.step(action)
    #     print(s.shape)
    #     print(info["private_state"].shape)
    # print(env.money_sold)
    # print(i)
    # import yaml
    # # args = parser.parse_args()

    # def save_dict_to_yaml(dict_value: dict, save_path: str):
    #     with open(save_path, 'w') as file:
    #         file.write(yaml.dump(dict_value, allow_unicode=True))

    # def read_yaml_to_dict(yaml_path: str, ):
    #     with open(yaml_path) as file:
    #         dict_value = yaml.load(file.read(), Loader=yaml.FullLoader)
    #         return dict_value

    # save_dict_to_yaml(
    #     vars(args),
    #     "/home/sunshuo/qml/TradeMaster-1/config/input_config/env/OE/OE_for_PD/valid.yml"
    # )


import os
import fnmatch
import yaml
from log import log

def get_node_info(node_dir, node_name):
    """
    Recurses down the directory trying to find filename wildcards that
    match the given filename. Returns the node info for the closest
    match.

    If there are two wildcards that match, the one that is more
    specific will win.

    Example:
        node_name = 'dev-sea1.api.example.com'

        files = os.listdir(node_dir)
        # Returns ['dev%','dev%.api.example.com', 'staging%']
        get_node_info(node_dir, node_name) = node info of 'dev%.api.example.com'

    Keyword arguments:
        node_dir -- the directory to start
        node_name -- the name of the host to match against
    """
    log.debug('entering node.get_node_info')
    result = _descend(node_dir, node_name)

    # sort by length with only the basename and with all hashes removed
    result.sort(lambda x,y: cmp(
        len(os.path.basename(x).translate(None, '%*')), # remove all percents
        len(os.path.basename(y).translate(None, '%*'))))# and asterisks

    ret = {}
    for r in result:
        with open(r) as node_file:
            ret.update(yaml.load(node_file.read()))

    log.debug('leaving node.get_node_info: %s', ret)
    return ret

def _descend(base_dir, node_name):
    """
    Recurses down the directory trying to find filename wildcards that
    match the given filename. Returns a list of all wildcards that match.

    Keyword arguments:
        base_dir -- the directory to start
        node_name -- the name of the host to match against
    """
    files = os.listdir(base_dir)
    result = []
    for f in files:
        srcfile = os.path.join(base_dir, f)
        if os.path.isdir(srcfile):
            result.extend(_descend(srcfile, node_name))
        else:
            if fnmatch.filter([node_name], f.replace('%','*')):
                result.append(srcfile)
    return result


from tkinter import *
from tkinter import messagebox
from tkinter import simpledialog
from tkinter import filedialog
from PIL import Image, ImageTk
from test import oneImg
from test import openCma
import cv2
import os
Flag = True #控制摄像头的变量
capture = cv2.VideoCapture(0)#摄像头对象作为全局变量会更快些

def ui_process():
    root =Tk()
    root.title("人脸检测系统")
    root.geometry("1000x850")

    tempImg=Image.open("D:/working/tensorflow_mtcnn_zip/tensorflow-MTCNN-master/bg.jpg")
    tempImg=tempImg.resize((1000,900))
    bgImg=ImageTk.PhotoImage(tempImg)
    theLabel = Label(root,image=bgImg,compound=CENTER)
    theLabel.pack()

#标签
    L_titile = Label(root,text='基于MTCNN的实时人脸检测系统',)
    L_titile.config(font='Helvetica -15 bold',fg='blue')
    L_titile.place(x=150,y=20,anchor="center")
    L_author = Label(root, text='作者:刘佳昇')
    L_author.config(font='Helvetica -10 bold')
    L_author.place(x=920,y=830)
    S_title = Label(root,text='图片识别模式')
    S_title.config(font='Helvetica -20 bold',fg='red')
    S_title.place(x=40,y=50)
    S_title = Label(root, text='摄像头实时识别模式')
    S_title.config(font='Helvetica -20 bold', fg='red')
    S_title.place(x=40, y=450)
    S_title = Label(root, text='图片识别结果')
    S_title.config(font='Helvetica -15 bold', fg='red')
    S_title.place(x=740, y=100)

#图区
    canvas = Canvas(root, bd=2, relief=SUNKEN)
    canvas.place(x=40,y=140)
    resultCanvas = Canvas(root,bd=2,relief=SUNKEN)
    resultCanvas.place(x=600,y=140)
    #摄像头
    cmaCanvas = Canvas(root,bd=2,relief=SUNKEN,height=350,width=580)
    cmaCanvas.place(x=400,y=470)

#按钮

    B_NO1 = Button(root, text="打开一张图片",command=lambda :OpenFile(canvas,resultCanvas))
    B_NO1.place(x=40, y=100)
    B_NO2 = Button(root, text="打开输出文件夹", command=lambda: openOutPut())
    B_NO2.place(x=600, y=100)
    B_OpenCma = Button(root,text="打开摄像头",command=lambda :openGuiCma(cmaCanvas,root))
    B_OpenCma.place(x=40,y=500)
    B_OpenCma = Button(root, text="关闭摄像头", command=lambda: closeGuiCma())
    B_OpenCma.place(x=140, y=500)

#菜单栏
    menubar = Menu(root)
    filemenu = Menu(menubar, tearoff=0)
    filemenu.add_command(label="Open", command=lambda :openOutPut())
    mainloop()

def openOutPut():
    os.system("start explorer D:\working\\tensorflow_mtcnn_zip\\tensorflow-MTCNN-master\\output")

#文件操作的对话框
def OpenFile(canvas,resultCanvas):
    File = filedialog.askopenfilename(title='打开图片', filetypes=[ ('All Files', '*')])
    print(type(File))
    # resultImg = ImageTk.PhotoImage(Image.fromarray(oneImg(File).astype('uint8')).convert('RGB')) #这个转换方式会导致颜色异常
    resultImg = ImageTk.PhotoImage(Image.fromarray(cv2.cvtColor(oneImg(File),cv2.COLOR_BGR2RGB)))  #这里需要把cv的图像格式转换成PIL.img
    filename = Image.open(File)
    # filename.resize((3500,300))
    filename = ImageTk.PhotoImage(filename)
    print(type(Image.open(File)))
    canvas.image = filename  # <--- keep reference of your image
    canvas.create_image(0, 0, anchor='nw', image=filename)
    resultCanvas.image = resultImg
    resultCanvas.create_image(0,0,anchor='nw',image=resultImg)
    print(File)

def closeGuiCma():
    global Flag
    print(Flag)
    Flag = False

def openGuiCma(resultCanvas,root):
    # 摄像头
    if(messagebox.askokcancel('Python Tkinter', '确认打开摄像头？')==True):
        global Flag
        Flag=True
        while Flag==True:
            ref, frame = capture.read()
            cvimage = cv2.cvtColor(openCma(frame), cv2.COLOR_BGR2RGBA)
            pilImage = Image.fromarray(cvimage)
            tkImage = ImageTk.PhotoImage(image=pilImage)
            resultCanvas.create_image(0, 0, anchor='nw', image=tkImage)
            root.update()
            root.after(100)

if __name__ == "__main__":
    print("开始")
    ui_process()


# 展示playwright工具的使用
from playwright.sync_api import sync_playwright

def run():
    with sync_playwright() as p:
        browser = p.chromium.launch()
        page = browser.new_page()
        page.goto('https://langchain.com/')
        title = page.title()
        print('title=', title)
        browser.close()

if __name__ == '__main__':
    run()


"""
Script to anonymize the classifications

The user names can be deleted and only user ids
are kept.
"""

import pandas as pd
import xarray as xr

raw_data_filename_input = '../zooniverse_raw/sugar-flower-fish-or-gravel-classifications.csv'
raw_data_filename_output = '../zooniverse_raw/sugar-flower-fish-or-gravel-classifications_anonymized.csv'

level1_data_filename_input = '../processed_data/EUREC4A_ManualClassifications_l1.nc'
level1_data_filename_output = '../processed_data/EUREC4A_ManualClassifications_l1_anonymized.nc'

# Anonymize raw data

df = pd.read_csv(raw_data_filename_input)
df = df.iloc[38003:]  # remove data from other classification days
del df['user_name']
df.to_csv(raw_data_filename_output)

# Anonymize level1 data
ds = xr.open_dataset(level1_data_filename_input)
del ds['user_name']
ds.to_netcdf(level1_data_filename_output)


'''
Created on Aug 5, 2020

@author: Jeff
'''
import PyQt5
from PyQt5 import QtCore, QtGui, QtWidgets
import datetime
import pyperclip

#Fixes scaling issues on high res monitors
if hasattr(QtCore.Qt, 'AA_EnableHighDpiScaling'):
    PyQt5.QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)

if hasattr(QtCore.Qt, 'AA_UseHighDpiPixmaps'):
    PyQt5.QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)

class SongDownloadView(object):
    '''
    classdocs
    '''

    def __init__(self, model, controller, MainWindow):
        self._model = model
        self._controller = controller
        self.setupUi(MainWindow)

        self._log           = '-----Start of Log-----\n'
        self._song_fail_log = ''

        self._model.song_total_change.connect(self.on_song_total_change)
        self._model.skipped_total_change.connect(self.on_skipped_total_change)
        self._model.song_download_change.connect(self.on_song_download_change)
        self._model.song_failed_change.connect(self.on_song_failed_change)
        self._model.song_progress_change.connect(self.on_update_progress)
        self._model.estimate_change.connect(self.on_estimate_update_change)
        self._model.log_change.connect(self.on_log_update)
        self._model.song_failed_name.connect(self.on_song_failed_update)
        self.start_download_button.clicked.connect(self.start_download_listener)

        self.normalize_audio.stateChanged.connect(self._controller.normalize_change)
        self.browse_csv_button.clicked.connect(self.get_csv_path)
        self.browse_output_button.clicked.connect(self.get_output_path)
        self.csv_file_location.textChanged.connect(self._controller.csv_file_change)
        self.output_file_location.textChanged.connect(self._controller.output_dir_change)

        self.download_retry_spinbox.valueChanged.connect(self._controller.download_try_change)
        self.retry_wait_time_spinbox.valueChanged.connect(self._controller.time_sleep_change)

        self.stop_download_button.clicked.connect(self.stop_download_listener)

        self.copy_log_button.clicked.connect(self.copy_log_listener)

    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(758, 500)
        MainWindow.setMinimumSize(QtCore.QSize(758, 500))
        MainWindow.setMaximumSize(QtCore.QSize(758, 500))
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayoutWidget_4 = QtWidgets.QWidget(self.centralwidget)
        self.gridLayoutWidget_4.setGeometry(QtCore.QRect(10, 10, 735, 421))
        self.gridLayoutWidget_4.setObjectName("gridLayoutWidget_4")
        self.gridLayout_4 = QtWidgets.QGridLayout(self.gridLayoutWidget_4)
        self.gridLayout_4.setContentsMargins(5, 0, 5, 0)
        self.gridLayout_4.setObjectName("gridLayout_4")
        self.start_download_button = QtWidgets.QPushButton(self.gridLayoutWidget_4)
        self.start_download_button.setMaximumSize(QtCore.QSize(100, 16777215))
        self.start_download_button.setObjectName("start_download_button")
        self.gridLayout_4.addWidget(self.start_download_button, 4, 0, 1, 1)
        self.log_output = QtWidgets.QPlainTextEdit(self.gridLayoutWidget_4)
        self.log_output.setEnabled(True)
        self.log_output.setReadOnly(True)
        self.log_output.setObjectName("log_output")
        self.gridLayout_4.addWidget(self.log_output, 12, 0, 1, 3)
        self.gridLayout = QtWidgets.QGridLayout()
        self.gridLayout.setContentsMargins(5, -1, 5, -1)
        self.gridLayout.setObjectName("gridLayout")
        self.skipped_songs_count = QtWidgets.QLCDNumber(self.gridLayoutWidget_4)
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Light, brush)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Midlight, brush)
        self.skipped_songs_count.setPalette(palette)
        self.skipped_songs_count.setEnabled(True)
        self.skipped_songs_count.setObjectName("skipped_songs_count")
        self.gridLayout.addWidget(self.skipped_songs_count, 2, 1, 1, 1)
        self.total_songs_count = QtWidgets.QLCDNumber(self.gridLayoutWidget_4)
        self.total_songs_count.setPalette(palette)
        self.total_songs_count.setObjectName("total_songs_count")
        self.gridLayout.addWidget(self.total_songs_count, 5, 1, 1, 1)
        self.total_songs_label = QtWidgets.QLabel(self.gridLayoutWidget_4)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.total_songs_label.setFont(font)
        self.total_songs_label.setObjectName("total_songs_label")
        self.gridLayout.addWidget(self.total_songs_label, 5, 0, 1, 1)
        self.downloaded_songs_count = QtWidgets.QLCDNumber(self.gridLayoutWidget_4)
        self.downloaded_songs_count.setPalette(palette)
        self.downloaded_songs_count.setObjectName("downloaded_songs_count")
        self.gridLayout.addWidget(self.downloaded_songs_count, 1, 1, 1, 1)
        self.downloaded_songs_label = QtWidgets.QLabel(self.gridLayoutWidget_4)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.downloaded_songs_label.setFont(font)
        self.downloaded_songs_label.setObjectName("downloaded_songs_label")
        self.gridLayout.addWidget(self.downloaded_songs_label, 1, 0, 1, 1)
        self.song_progress_bar = QtWidgets.QProgressBar(self.gridLayoutWidget_4)
        self.song_progress_bar.setProperty("value", 0)
        self.song_progress_bar.setObjectName("song_progress_bar")
        self.gridLayout.addWidget(self.song_progress_bar, 6, 0, 1, 2)
        self.skipped_songs_label = QtWidgets.QLabel(self.gridLayoutWidget_4)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.skipped_songs_label.setFont(font)
        self.skipped_songs_label.setObjectName("skipped_songs_label")
        self.gridLayout.addWidget(self.skipped_songs_label, 2, 0, 1, 1)
        self.progress_label = QtWidgets.QLabel(self.gridLayoutWidget_4)
        font = QtGui.QFont()
        font.setPointSize(18)
        self.progress_label.setFont(font)
        self.progress_label.setAlignment(QtCore.Qt.AlignCenter)
        self.progress_label.setObjectName("progress_label")
        self.gridLayout.addWidget(self.progress_label, 0, 0, 1, 2)
        self.failed_songs_count_label = QtWidgets.QLabel(self.gridLayoutWidget_4)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.failed_songs_count_label.setFont(font)
        self.failed_songs_count_label.setObjectName("failed_songs_count_label")
        self.gridLayout.addWidget(self.failed_songs_count_label, 3, 0, 1, 1)
        self.failed_songs_count = QtWidgets.QLCDNumber(self.gridLayoutWidget_4)
        self.failed_songs_count.setPalette(palette)
        self.failed_songs_count.setEnabled(True)
        self.failed_songs_count.setObjectName("failed_songs_count")
        self.gridLayout.addWidget(self.failed_songs_count, 3, 1, 1, 1)
        self.gridLayout_4.addLayout(self.gridLayout, 0, 4, 4, 1)
        self.time_remaining_label = QtWidgets.QLabel(self.gridLayoutWidget_4)
        font = QtGui.QFont()
        font.setPointSize(8)
        self.time_remaining_label.setFont(font)
        self.time_remaining_label.setObjectName("time_remaining_label")
        self.gridLayout_4.addWidget(self.time_remaining_label, 4, 4, 1, 1)
        self.failed_songs_label = QtWidgets.QLabel(self.gridLayoutWidget_4)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.failed_songs_label.setFont(font)
        self.failed_songs_label.setObjectName("failed_songs_label")
        self.gridLayout_4.addWidget(self.failed_songs_label, 11, 3, 1, 2)
        self.log_label = QtWidgets.QLabel(self.gridLayoutWidget_4)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.log_label.setFont(font)
        self.log_label.setObjectName("log_label")
        self.gridLayout_4.addWidget(self.log_label, 11, 0, 1, 2)
        self.stop_download_button = QtWidgets.QPushButton(self.gridLayoutWidget_4)
        self.stop_download_button.setEnabled(False)
        self.stop_download_button.setMaximumSize(QtCore.QSize(100, 16777215))
        self.stop_download_button.setAutoFillBackground(False)
        self.stop_download_button.setObjectName("stop_download_button")
        self.gridLayout_4.addWidget(self.stop_download_button, 4, 2, 1, 1)
        self.gridLayout_2 = QtWidgets.QGridLayout()
        self.gridLayout_2.setContentsMargins(5, -1, -1, -1)
        self.gridLayout_2.setObjectName("gridLayout_2")
        self.browse_output_button = QtWidgets.QPushButton(self.gridLayoutWidget_4)
        self.browse_output_button.setMaximumSize(QtCore.QSize(150, 16777215))
        self.browse_output_button.setObjectName("browse_output_button")
        self.gridLayout_2.addWidget(self.browse_output_button, 1, 1, 1, 1)
        self.setup_label = QtWidgets.QLabel(self.gridLayoutWidget_4)
        font = QtGui.QFont()
        font.setPointSize(18)
        self.setup_label.setFont(font)
        self.setup_label.setAlignment(QtCore.Qt.AlignCenter)
        self.setup_label.setObjectName("setup_label")
        self.gridLayout_2.addWidget(self.setup_label, 0, 1, 1, 2)
        self.browse_csv_button = QtWidgets.QPushButton(self.gridLayoutWidget_4)
        self.browse_csv_button.setMaximumSize(QtCore.QSize(150, 16777215))
        self.browse_csv_button.setObjectName("browse_csv_button")
        self.gridLayout_2.addWidget(self.browse_csv_button, 2, 1, 1, 1)
        self.output_file_location = QtWidgets.QLineEdit(self.gridLayoutWidget_4)
        self.output_file_location.setReadOnly(True)
        self.output_file_location.setObjectName("output_file_location")
        self.gridLayout_2.addWidget(self.output_file_location, 1, 2, 1, 1)
        self.csv_file_location = QtWidgets.QLineEdit(self.gridLayoutWidget_4)
        self.csv_file_location.setReadOnly(True)
        self.csv_file_location.setObjectName("csv_file_location")
        self.gridLayout_2.addWidget(self.csv_file_location, 2, 2, 1, 1)
        self.gridLayout_3 = QtWidgets.QGridLayout()
        self.gridLayout_3.setObjectName("gridLayout_3")
        self.download_retry_spinbox = QtWidgets.QSpinBox(self.gridLayoutWidget_4)
        self.download_retry_spinbox.setMinimum(1)
        self.download_retry_spinbox.setProperty("value", 5)
        self.download_retry_spinbox.setObjectName("download_retry_spinbox")
        self.gridLayout_3.addWidget(self.download_retry_spinbox, 2, 4, 1, 1)
        self.download_retry_label = QtWidgets.QLabel(self.gridLayoutWidget_4)
        self.download_retry_label.setToolTip("")
        self.download_retry_label.setObjectName("download_retry_label")
        self.gridLayout_3.addWidget(self.download_retry_label, 2, 3, 1, 1)
        self.configuration_label = QtWidgets.QLabel(self.gridLayoutWidget_4)
        font = QtGui.QFont()
        font.setPointSize(18)
        self.configuration_label.setFont(font)
        self.configuration_label.setAlignment(QtCore.Qt.AlignCenter)
        self.configuration_label.setObjectName("configuration_label")
        self.gridLayout_3.addWidget(self.configuration_label, 0, 1, 1, 4)
        self.retry_wait_time_spinbox = QtWidgets.QSpinBox(self.gridLayoutWidget_4)
        self.retry_wait_time_spinbox.setMinimum(2)
        self.retry_wait_time_spinbox.setObjectName("retry_wait_time_spinbox")
        self.gridLayout_3.addWidget(self.retry_wait_time_spinbox, 2, 2, 1, 1)
        self.retry_wait_time_label = QtWidgets.QLabel(self.gridLayoutWidget_4)
        self.retry_wait_time_label.setToolTip("")
        self.retry_wait_time_label.setObjectName("retry_wait_time_label")
        self.gridLayout_3.addWidget(self.retry_wait_time_label, 2, 1, 1, 1)
        self.normalize_audio = QtWidgets.QCheckBox(self.gridLayoutWidget_4)
        font = QtGui.QFont()
        font.setPointSize(12)
        self.normalize_audio.setFont(font)
        self.normalize_audio.setChecked(True)
        self.normalize_audio.setObjectName("normalize_audio")
        self.gridLayout_3.addWidget(self.normalize_audio, 1, 1, 1, 1)
        self.gridLayout_2.addLayout(self.gridLayout_3, 3, 1, 1, 2)
        self.gridLayout_4.addLayout(self.gridLayout_2, 0, 0, 1, 4)
        self.failed_songs_log = QtWidgets.QPlainTextEdit(self.gridLayoutWidget_4)
        self.failed_songs_log.setEnabled(True)
        self.failed_songs_log.setReadOnly(True)
        self.failed_songs_log.setObjectName("failed_songs_log")
        self.gridLayout_4.addWidget(self.failed_songs_log, 12, 3, 1, 2)
        self.copy_log_button = QtWidgets.QPushButton(self.gridLayoutWidget_4)
        self.copy_log_button.setObjectName("copy_log_button")
        self.gridLayout_4.addWidget(self.copy_log_button, 11, 2, 1, 1)
        self.version_label = QtWidgets.QLabel(self.centralwidget)
        self.version_label.setGeometry(QtCore.QRect(330, 460, 81, 16))
        self.version_label.setObjectName("version_label")
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "Music Downloader"))
        self.start_download_button.setText(_translate("MainWindow", "Start Download"))
        self.total_songs_label.setText(_translate("MainWindow", "Total Songs:"))
        self.downloaded_songs_label.setText(_translate("MainWindow", "Songs Downloaded:"))
        self.skipped_songs_label.setText(_translate("MainWindow", "Songs Skipped:"))
        self.progress_label.setText(_translate("MainWindow", "Progress"))
        self.failed_songs_count_label.setText(_translate("MainWindow", "Songs Failed:"))
        self.time_remaining_label.setText(_translate("MainWindow", "Estimated Time Remaining: "))
        self.failed_songs_label.setText(_translate("MainWindow", "Failed Songs:"))
        self.log_label.setText(_translate("MainWindow", "Log:"))
        self.stop_download_button.setText(_translate("MainWindow", "Stop Download"))
        self.browse_output_button.setText(_translate("MainWindow", "Select Output Directory"))
        self.setup_label.setText(_translate("MainWindow", "Setup"))
        self.browse_csv_button.setText(_translate("MainWindow", "Select CSV File"))
        self.download_retry_label.setText(_translate("MainWindow", "Download Attempts"))
        self.configuration_label.setText(_translate("MainWindow", "Configuration"))
        self.retry_wait_time_label.setText(_translate("MainWindow", "Time to Wait Between Tries"))
        self.normalize_audio.setText(_translate("MainWindow", "Normalize Audio"))
        self.copy_log_button.setText(_translate("MainWindow", "Copy Log to Clipboard"))
        self.version_label.setText(_translate("MainWindow", "Version 1.0.0"))

    def on_song_total_change(self, value):
        self.total_songs_count.display(value)

    def on_skipped_total_change(self, value):
        self.skipped_songs_count.display(value)

    def on_song_download_change(self, value):
        self.downloaded_songs_count.display(value)

    def on_song_failed_change(self, value):
        self.failed_songs_count.display(value)

    def on_update_progress(self, value):
        self.song_progress_bar.setValue(value)

    def on_estimate_update_change(self, value):
        self.time_remaining_label.setText('Estimated Time Remaining: ' + value)

    def on_log_update(self, value):
        now = datetime.datetime.now()
        date = str(now.year) + '-' + str(now.month) + '-' + str(now.day) + ' '+ str(now.hour) + ':' + str(now.minute) + ':' + str(now.second)
        self._log = self._log +'['+ date +']'+ value + '\n'
        self.log_output.setPlainText(self._log)
        self.log_output.verticalScrollBar().setValue(self.log_output.verticalScrollBar().maximum())

    def on_song_failed_update(self, value):
        self._song_fail_log = self._song_fail_log + value + '\n'
        self.failed_songs_log.setPlainText(self._song_fail_log)
        self.failed_songs_log.verticalScrollBar().setValue(self.failed_songs_log.verticalScrollBar().maximum())

    def get_csv_path(self):
        file = QtWidgets.QFileDialog().getOpenFileName(None, 'Select CSV', '', '*.csv')
        file_path = file[0]
        file_path = file_path.replace('/', '\\' )
        self.csv_file_location.setText(file_path)

    def get_output_path(self):
        file_path = QtWidgets.QFileDialog().getExistingDirectory()
        file_path = file_path.replace('/', '\\' )
        self.output_file_location.setText(file_path)

    def start_download_listener(self):
        self.start_download_button.setDisabled(True)
        self.stop_download_button.setDisabled(False)
        self._controller.start_download_click()

    def stop_download_listener(self):
        self.start_download_button.setDisabled(False)
        self.stop_download_button.setDisabled(True)
        self._controller.stop_download_click()

    def copy_log_listener(self):
        copy_value = self.log_output.toPlainText()
        pyperclip.copy(copy_value)


import matplotlib.pyplot as plt
import numpy as np

def plot_histogram(data, title, output_filename):
    plt.rc('text', usetex=True)
    plt.rc('font', family='serif')

    fig, axis = plt.subplots()
    X = data[:,0]
    Y = data[:,1]
    axis.set_xlabel(r'association count', fontsize=15)
    axis.set_ylabel(r'number of edges', fontsize=15)

    # add an extra bin for 0
    apx_num_bins = 100
    step = int(X.max()/apx_num_bins)
    bins = range(-step+1, int(X.max())+step+1, step)

    plt.hist(X, bins, weights=Y, log=True, histtype='bar', color='green', align='right')
    plt.savefig(output_filename, bbox_inches='tight')

titles = [ '100000', '100', '25', '400', 'osmGerHist' ]
datasets = [ '100000hist', '100hist', '25hist', '400hist', 'osmGerHist' ]

for i in range(0, len(datasets)):
    dataset = datasets[i]
    title = titles[i]
    data = np.loadtxt('../data/' + dataset)
    output_filename = dataset + '.pdf'
    plot_histogram(data, "\\textsc{" + title.capitalize() + "}", output_filename)


import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from networks.deep_lab import DeepLabv3_plus
from collections import OrderedDict
from networks.tools import save_image
from networks import tools

# The Code of baseline network is referenced from https://github.com/icoz69/CaNet
# The code of training & testing is referenced from https://github.com/xiaomengyc/SG-One

class network(nn.Module):
    """
    Fewshot Segmentation model

    Args:
        in_channels:
            number of input channels
        pretrained_path:
            path of the model for initialization
        cfg:
            model configurations
    """
    def __init__(self, num_heads=15): # + background  part:29  ori:15
        super().__init__()
        self.num_heads = num_heads

        # Encoder os=8
        self.encoder = nn.Sequential(OrderedDict([('backbone', DeepLabv3_plus(nInputChannels=3, n_classes=num_heads, os=16, pretrained=True, _print=True))]))
        #self.encoder = nn.Sequential(OrderedDict([('backbone', Encoder(pretrained_path='./pretrained_model/vgg16-397923af.pth'))]))

        self.GMP = nn.AdaptiveMaxPool2d((1,1))
        self.GAP = nn.AdaptiveAvgPool2d((1,1))

        self.save_pred_list = []
        self.save_bipred_list = []
        self.save_mask_list = []
        self.save_part_mask_list = []

        self.loss_weights = torch.tensor([1.72, 46.1, 47.2, 32.4, 40.9, 49.2, 49.8, 48.7, 47.5, 50.4, 11.8, 49.8,
                                         16.9, 45.1, 32.9, 38.6, 45.3, 50.0, 22.2, 50.1, 39.9, 36.3, 44.0, 29.9,
                                         32.4, 47.8, 45.8, 41.6, 37.9]).type(torch.cuda.FloatTensor)

        # self.loss_weights = torch.tensor([1.80, 33.0, 37.4, 38.4, 18.9, 17.7, 34.5, 9.9, 37.2, 34.0, 23.5, 31.2,
        #                                  34.2, 30.0, 30.2]).type(torch.cuda.FloatTensor)

    def forward(self, img):
        # Extractor
        fts,_ = self.encoder(img) # torch.Size([8, 256, 28, 28])
        fts = F.interpolate(fts, size=img.size()[2:], mode='bilinear', align_corners=True)
        return fts

    def forward_gcn(self, img, mask): # (32,3,224,224)
        b,c,w,h = img.size()

        _, fts = self.encoder(img)  # torch.Size([32, 44, 224, 224]),torch.Size([32, 256, 56, 56])

        mask_c = torch.zeros_like(mask)
        mask_c[mask!=0] = 1.0
        mask_c = F.interpolate(mask_c, size=fts.shape[-2:], mode='bilinear', align_corners=True)

        fts = fts * mask_c #* mask # torch.Size([32, 256, 56, 56])
        fts = self.GAP(fts).view(fts.size(0), -1)

        sum = 0
        count = 0
        for i, itemi in enumerate(fts):
            for j, itemj in enumerate(fts[i+1:]):
                cos = F.cosine_similarity(itemi, itemj, dim=0)
                sum += cos.item()
                count += 1
        return sum/count

    def get_loss(self, cos_map, part_mask):
        b,c,w,h = cos_map.size()
        #loss_fuc = torch.nn.MSELoss(size_average = False)

        loss_fuc = torch.nn.CrossEntropyLoss(weight=self.loss_weights)
        #cos_map = cos_map * part_idx[:, :, None, None]
        mse_loss = loss_fuc(cos_map, part_mask[:,0,:,:].type(torch.cuda.LongTensor))# torch.Size([8, 43, 224, 224])
        return mse_loss

    def save_pred(self,cos_map, mask, part_mask, ii, mode, img=None, cat_idx=None): # torch.Size([8, 43, 224, 224])  torch.Size([8, 224, 224])
        b,c,w,h = cos_map.size()

        mask = mask.detach().cpu().numpy()[:, 0, :, :]

        cos_map = cos_map.detach().cpu().numpy()
        cos_map = np.argmax(cos_map, axis=1)
        bi_cos_map = np.zeros_like(cos_map)
        bi_cos_map[cos_map!=0]=1
        # category = np.unique(mask)[1]
        # bi_cos_map[cos_map != 0] = category

        if mode == 'train' or mode == 'test_voc':
            mask[mask != 0] = 1
            part_mask = part_mask.detach().cpu().numpy()
            save_map = np.concatenate((cos_map, part_mask[:,0,:,:], bi_cos_map, mask), axis=2)
            for j, item in enumerate(save_map):
                tools.labelTopng(item[:,:224], 'for_paper/%d_%d_attpred.png'%(ii,j))
                tools.labelTopng(item[:, 224:448], 'for_paper/%d_%d_attgt.png' % (ii, j))
                tools.labelTopng(item[:, 448:672], 'for_paper/%d_%d_bipred.png' % (ii, j), mode='binary')
                tools.labelTopng(item[:, 672:], 'for_paper/%d_%d_bigt.png' % (ii, j), mode='binary')
                img_s = img[j].cpu().numpy()
                img_s = img_s.swapaxes(0,1).swapaxes(1,2)
                img_s = tools.norm_image(img_s)
                save_image(img_s, 'for_paper/%d_%d_img.jpg'%(ii,j))

            for i in range(b):
                self.save_pred_list.append(np.uint8(cos_map[i]))
                self.save_bipred_list.append(np.uint8(bi_cos_map[i]))
                self.save_mask_list.append(np.uint8(mask[i]))
                self.save_part_mask_list.append(np.uint8(part_mask[i]))

        elif mode == 'test_coco':
            mask[mask != cat_idx] = 0
            mask[mask == cat_idx] = 1
            save_map = np.concatenate((bi_cos_map, mask), axis=2)
            # for j, item in enumerate(save_map):
            #     idx = cat_idx[j]
            #     tools.labelTopng(item[:,:224], 'for_paper_semantic/%d_%d_bipred.png'%(ii,j))
            #     tools.labelTopng(item[:, 224:448], 'for_paper_semantic/%d_%d_bigt.png' % (ii, j))
            #     img_s = img[j].cpu().numpy()
            #     img_s = img_s.swapaxes(0,1).swapaxes(1,2)
            #     img_s = tools.norm_image(img_s)
            #     save_image(img_s, 'for_paper_semantic/%d_%d_img.jpg'%(ii,j))
            for i in range(b):
                self.save_bipred_list.append(np.uint8(bi_cos_map[i]))
                self.save_mask_list.append(np.uint8(mask[i]))

    def save_semantic(self,cos_map, mask,ii): # torch.Size([8, 43, 224, 224])  torch.Size([8, 224, 224])
        b,w,h = cos_map.shape
        mask = mask[:,0]
        save_map = np.concatenate((cos_map, mask), axis=2)
        for i in range(b):
            #print(np.unique(cos_map[i]), np.unique(mask[i]))
            tools.labelTopng(save_map[i], 'check_semantic/%d_%d.png'%(ii,i))
            self.save_pred_list.append(np.uint8(cos_map[i]))
            self.save_mask_list.append(np.uint8(mask[i]))

    def get_pred(self, mode='train'):
        if mode == 'train' or mode == 'test_voc':
            _,_,miou,_ = tools.compute_miou(self.save_bipred_list, self.save_mask_list, n_class=2)
            _, _, part_miou, _ = tools.compute_miou(self.save_pred_list, self.save_part_mask_list, n_class=self.num_heads)
            self.save_pred_list = []
            self.save_bipred_list = []
            self.save_mask_list = []
            self.save_part_mask_list = []
            return miou, part_miou

        elif mode == 'test_coco':
            _,_,miou,_ = tools.compute_miou(self.save_bipred_list, self.save_mask_list, n_class=2)
            self.save_pred_list = []
            self.save_bipred_list = []
            self.save_mask_list = []
            self.save_part_mask_list = []
            return miou, 0.0

    def get_pred_semantic(self):
        _,_,miou,_ = tools.compute_miou(self.save_pred_list, self.save_mask_list, n_class=21)
        self.save_pred_list = []
        self.save_bipred_list = []
        self.save_mask_list = []
        self.save_part_mask_list = []
        return miou


from airflow.hooks.postgres_hook import PostgresHook
from airflow.models import BaseOperator
from helpers import SqlQueries

class LoadFactOperator(BaseOperator):
    ui_color = '#F98866'

    load_fact_table_insert = """
    INSERT INTO {} {}
    """
    load_fact_table_truncate = """
    TRUNCATE TABLE {}
    """

    def __init__(self,
                 sql="",
                 conn_id="",
                 table="",
                 mode="",
                 *args, **kwargs):
        super(LoadFactOperator, self).__init__(*args, **kwargs)
        self.sql = sql
        self.conn_id = conn_id
        self.table = table
        self.mode = mode

    def execute(self, context):

        redshift = PostgresHook(postgres_conn_id=self.conn_id)

        if (self.mode == "append"):
            redshift.run(LoadFactOperator.load_fact_table_insert.format(self.table, self.sql))

        if (self.mode == "truncate"):
            redshift.run(LoadFactOperator.load_fact_table_truncate.format(self.table))
            redshift.run(LoadFactOperator.load_fact_table_insert.format(self.table, self.sql))

            # self.log.info(f"Successful completion of {self.mode} on {self.table}")


# -*- coding: utf-8 -*-
"""
Created on Mon Feb  6 16:11:33 2023

@author: SWannell
"""

import matplotlib.pyplot as plt; plt.style.use('ggplot')
import matplotlib.ticker as mtick
import pandas as pd

df = pd.read_csv('AmendedData\\appeal_by_hour.csv', parse_dates=['datehour'])
df.info()

appeal_types = {'Turkey-Syria': '#ee2a24',
                'Haiti': '#850000',
                'Pakistan': '#f86652',
                'Beirut': '#652c4a',
                'Global Coronavirus': '#158aba',
                'National Emergencies Trust': '#1a3351',
                'Afghanistan': '#714200',
                'Ukraine': '#f1b13b'
                }

colour_list = [appeal_types[c] for c in df['appeal'].unique()]

# Plot the first chunk
days = 16
figs, axs = plt.subplots(2, 1, sharex=True, figsize=(8, 10))
for appeal, c in appeal_types.items():
    df_slice = df.loc[df['appeal'] == appeal, ['datehour', 'gifts']]
    df_slice.set_index('datehour', inplace=True)
    df_slice = df_slice.resample('H').sum()
    df_slice = df_slice.reset_index(drop=True)
    # Plot standard
    df_slice.loc[:days*24-1].plot(ax=axs[1], linewidth=3, color=c)
    # Plot cumu
    df_slice_cumu = df_slice.cumsum()
    df_slice_cumu.loc[:days*24-1].plot(ax=axs[0], linewidth=3, color=c)
# Check that resample is working
# [i for i in pd.date_range('2022-02-24', '2022-03-02', freq='H')[:-1] if i not in df_slice.index]
# Format the plot
thoufmt = mtick.StrMethodFormatter('{x:,.0f}')
for ax in axs:
    ax.set_xlim(0)
    ax.set_ylim(0)
    ax.yaxis.set_major_formatter(thoufmt)
# Bottom plot
axs[1].set_ylabel('Gifts')
axs[1].legend().set_visible(False)
day_range = range(0, 24*(days+1), 24)
if days < 4:
    axs[1].set_xticks(day_range)  # label the hours
    axs[1].set_title('By hour', fontsize=15)
    axs[1].set_xlabel('Hours')
else:
    xlist = [[''] * 23 + [i] for i in range(days+1)]
    xlist = [item for sublist in xlist for item in sublist]
    axs[1].set_xticks(day_range, range(0, days+1))  # label the days
    axs[1].set_title('By day', fontsize=15)
    axs[1].set_xlabel('Days')
axs[1].set_ylim(0, 2000)
# Top cumu plot
axs[0].set_ylabel('Gifts (cumulative)')
axs[0].legend(labels=appeal_types.keys())
axs[0].set_title('Cumulative', fontsize=15)
annot = "Data from Google Analytics. 'First week' starts on first 500+ gift\
 day."
figs.text(0.05, 0, annot, color='#1d1a1c', fontsize=10, alpha=0.5)
plt.suptitle('Appeal volumes from launch', fontsize=30)
plt.tight_layout()

# Save plot
last_appeal = df[df['datehour'] == df['datehour'].max()]['appeal'].values[0]
plt.savefig(f'Outputs\\first_{days}_days_{last_appeal}.png')


import numpy as np

import pandas as pd

from fastai.vision import *

from fastai import *

import zipfile

import torch.nn as nn

import os

# print(os.listdir("../input/carvana-image-masking-challenge"))
def unzip_file(path_name):

    with zipfile.ZipFile(path_name, 'r') as zip_ref:

        zip_ref.extractall("/kaggle/working/")
unzip_file("/kaggle/input/carvana-image-masking-challenge/train_masks.zip")

unzip_file("/kaggle/input/carvana-image-masking-challenge/train.zip")
from subprocess import check_output

print(check_output(["ls", "/kaggle/working/"]).decode("utf8"))
path = Path("/kaggle/working/")
image_path = path/"train"

mask_path = path/"train_masks"
img = open_image("/kaggle/input/carvana-image-masking-challenge/29bb3ece3180_11.jpg")

img.show(figsize = (5,5))

img.shape
images = get_image_files("/kaggle/working/train")

images.sort()

images[:5]
masks = get_image_files("/kaggle/working/train_masks")

masks.sort()

masks[:4]
get_masks = lambda x: mask_path/f'{x.stem}_mask.gif'
msk = open_mask(get_masks(images[1]), div = True)

msk.show(figsize = (10,7))
class LabelList(SegmentationLabelList):

    def open(self,fn):

        return open_mask(fn, div=True)

class ItemList(ImageList):

    _label_cls= LabelList
#Defining the dataset

src_size = np.array(msk.shape[1:])

size = src_size//4

codes = ["background", "car"]

# size = 224

bs = 4

src = (ItemList.from_folder(image_path)

       .use_partial_data(sample_pct=0.1)

       .split_by_rand_pct(0.2,42)

       .label_from_func(get_masks, classes = codes))
data = (src.transform(get_transforms(), size = size, tfm_y = True)

        .databunch(bs=bs)

        .normalize(imagenet_stats))
data.show_batch(2,figsize = (7,7))
data.show_batch(2,figsize = (7,7), ds_type = DatasetType.Valid)
wd = 1e-2

learn = unet_learner(data, models.resnet50, metrics = [dice], wd = wd).to_fp16()
learn.lr_find()

learn.recorder.plot()
lr = 1e-03

learn.fit_one_cycle(3,slice(lr), pct_start = 0.9)
learn.save('stage-1')
learn.load('stage-1')
learn.unfreeze()
# common practice

lrs = slice(lr/400, lr/4)
learn.fit_one_cycle(5, lrs, pct_start = 0.8)


from http.client import HTTPResponse
from django.contrib import admin
from django.urls import path
from django.http import HttpResponseRedirect
from django.shortcuts import render

tasks = []
completed_tasks = []

def task_view(request):
    return render(request, "tasks.html", {"tasks": tasks})

def add_task_view(request):
    task_string = request.GET.get("task")
    tasks.append(task_string)
    return HttpResponseRedirect("/tasks")

def delete_task_view(request, index):
    del tasks[index - 1]
    return HttpResponseRedirect("/tasks")

def complete_task(requests, index):
    # moving task from tasks to completed tasks
    task_string = tasks[index - 1]
    del tasks[index - 1]
    completed_tasks.append(task_string)
    return HttpResponseRedirect("/tasks")

def completed_task_view(request):
    return render(request, "completed_tasks.html", {"tasks": completed_tasks})

urlpatterns = [
    path("admin/", admin.site.urls),
    path("tasks/", task_view),
    path("add-task/", add_task_view),
    path("delete-task/<int:index>/", delete_task_view),
    path("complete_task/<int:index>/", complete_task),
    path("completed_tasks/", completed_task_view)
    # Add all your views here
]


"""
1499. Max Value of Equation
You are given an array points containing the coordinates of points on a 2D plane, sorted by the x-values, where points[i] = [x_i, y_i] such that x_i < x_y for all 1 <= i < j <= points.length. You are also given an integer k

Return the maximum value of the equation y_i + y_j + |x_i - x_j| where |x_i - x_j| <= k and 1 <= i < j <= points.length.

It is guaranteed that there exists at least one pair of points that satisfy the constraint |x_i - x_j| <= k.

Example1:
Input: points = [[1,3],[2,0],[5,10],[6,-10]], k = 1
Output: 4
Explanation: The first two points satisfy the condition |xi - xj| <= 1 and if we calculate the equation we get 3 + 0 + |1 - 2| = 4. Third and fourth points also satisfy the condition and give a value of 10 + -10 + |5 - 6| = 1.
No other pairs satisfy the condition, so we return the max of 4 and 1.

Example2:
Input: points = [[0,0],[3,0],[9,2]], k = 3
Output: 3
Explanation: Only the first two points have an absolute difference of 3 or less in the x-values, and give the value of 0 + 0 + |0 - 3| = 3.

Constraints:
2 <= points.length <= 10^5
points[i].length == 2
-10^8 <= x_i, y_i <= 10^8
0 <= k <= 2 * 10^8
x_i < x_j for all 1 <= i < j <= points.length
x_i form a strictly increasing sequence.
"""

"""
Note:
1. maxHeap: O(nlogn) time | O(n) space - where n is the number of points
2. monotonic queue: O(n) time | O(n) space - where n is the number of points
"""

import collections
from typing import List
import unittest
import heapq
class Solution:
    def findMaxValueOfEquation(self, points: List[List[int]], k: int) -> int:
        # yi + yj + | xi - xj | = (yi - xi) + (yj + xj)
        # |x_i - x_j| <= k
        maxVal = float("-inf")
        maxHeap = []
        for x, y in points:
            # x - maxHeap = |x_i - x_j|
            # pop out invalid points
            while maxHeap and x - maxHeap[0][1] > k:
                heapq.heappop(maxHeap)

            if maxHeap:
                # -maxHeap[0][0] = (yi - xi)
                # y + x = y_j + x_j
                maxVal = max(maxVal, -maxHeap[0][0] + (y + x))

            heapq.heappush(maxHeap, (-(y - x), x))
        return maxVal

    def findMaxValueOfEquation2(self, points: List[List[int]], k: int) -> int:
        # yi + yj + | xi - xj | = (yi - xi) + (yj + xj)
        maxVal = float("-inf")
        queue = collections.deque()

        for x, y in points:
            while queue and x - queue[0][1] > k:
                queue.popleft()

            if queue:
                maxVal = max(maxVal, queue[0][0] + (y + x))

            # queue[-1][0] = (yi - xi)
            # pop out all candidates with smaller yi - xi
            while queue and queue[-1][0] <= y - x:
                queue.pop()

            queue.append((y - x, x))
        return maxVal

# Unit Tests
funcs = [Solution().findMaxValueOfEquation, Solution().findMaxValueOfEquation2]

class TestFindMaxValueOfEquation(unittest.TestCase):
    def testFindMaxValueOfEquation1(self):
        for func in funcs:
            points = [[1, 3], [2, 0], [5, 10], [6, -10]]
            k = 1
            self.assertEqual(func(points=points, k=k), 4)

    def testFindMaxValueOfEquation2(self):
        for func in funcs:
            points = [[0, 0], [3, 0], [9, 2]]
            k = 3
            self.assertEqual(func(points=points, k=k), 3)

if __name__ == "__main__":
    unittest.main()


## Code for PGD attacker
import torch
import torch.nn.functional as F

class PGDAttacker(object):

    def __init__(self, attack_eps):
        self.attack_eps = attack_eps

    def attack(self, x, y, net, attack_steps, attack_lr, random_init=True, target=None, clamp=(0, 1)):
        """
        :param x: Inputs to perturb
        :param y: Corresponding ground-truth labels
        :param net: Network to attack
        :param attack_steps: Number of attack iterations
        :param attack_lr: Learning rate of attacker
        :param random_init: If true, uses random initialization
        :param target: If not None, attacks to the chosen class. Dimension of target should be same as labels
        :return:
        """

        x_adv = x.clone()

        if random_init:
            # Flag to use random initialization
            x_adv = x_adv + (torch.rand(x.size(), dtype=x.dtype, device=x.device) - 0.5) * 2 * self.attack_eps

        for i in range(attack_steps):
            x_adv.requires_grad = True

            net.zero_grad()
            logits = net(x_adv)

            if target is None:
                # Untargeted attacks - gradient ascent
                loss = F.cross_entropy(logits, y)
                loss.backward()
                grad = x_adv.grad.detach()
                grad = grad.sign()
                x_adv = x_adv + attack_lr * grad

            else:
                # Targeted attacks - gradient descent
                assert target.size() == y.size()
                loss = F.cross_entropy(logits, target)
                loss.backward()
                grad = x_adv.grad.detach()
                grad = grad.sign()
                x_adv = x_adv - attack_lr * grad

            # Projection
            x_adv = x + torch.clamp(x_adv - x, min=-self.attack_eps, max=self.attack_eps)
            x_adv = x_adv.detach()
            x_adv = torch.clamp(x_adv, *clamp)

        return x_adv


from django.shortcuts import render, redirect, reverse
from django.urls import reverse_lazy
from django.views.generic import ListView, DetailView, FormView, DeleteView, UpdateView
from books.models import Book
from . import forms

# Create your views here.
class BooksView(ListView):
    """Show the Book lists"""

    model = Book
    paginate_by = 10
    paginate_orphans = 5
    ordering = "-created_at"
    context_object_name = "books"

class BookDetail(DetailView):
    """Show the book detail"""

    model = Book
    context_object_name = "book"

class BookCreate(FormView):
    """ Create new books"""
    form_class = forms.CreateBookForm
    template_name = "books/book_create.html"

    def get(self, request):
        form = self.get_form()
        return render(request, "books/book_create.html", {"form": form})

    def post(self, request, *args, **kwargs):
        form = self.get_form()
        if form.is_valid():

            book = form.save()
            book.save()
            return redirect(reverse("books:book", kwargs={"pk": book.pk}))
        else:

            return render(request, "books/book_create.html", {"form": form})

class BookUpdate(UpdateView):
    model = Book
    template_name = "books/book_update.html"
    success_url = reverse_lazy("books:books")
    fields = ("title",
              "year",
              "rating",
              "cover_image",
              "category",
              "writer",
              "storyline",)

class BookDelete(DeleteView):
    """ Delete book information """
    model = Book
    success_url = reverse_lazy("books:books")

    def get(self, request, *args, **kwargs):
        return self.post(request, *args, **kwargs)


import pyaudio
import socket
import threading
import wave
import asyncio
import sys
import boto3

from queue import Queue
from datetime import date, datetime
from amazon_transcribe.client import TranscribeStreamingClient
from amazon_transcribe.handlers import TranscriptResultStreamHandler
from amazon_transcribe.model import TranscriptEvent

queue = Queue()
no_data = False
s3 = boto3.client('s3')
translate = boto3.client('translate')
db_obj = boto3.resource('dynamodb')
table = db_obj.Table('<table>')
region = '<region>'
bucket_name = '<bucket>'

class SoundStreamServer(threading.Thread):
    def __init__(self, server_host, server_port):
        threading.Thread.__init__(self)
        self.SERVER_HOST = server_host
        self.SERVER_PORT = int(server_port)

    def run(self):
        audio = pyaudio.PyAudio()
        global queue, no_data

        # ファイル出力先
        # filepath = "sample.wav"

        # サーバーソケット生成
        with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_sock:
            server_sock.bind((self.SERVER_HOST, self.SERVER_PORT))
            server_sock.listen(1)

            # クライアントと接続
            client_sock, _ = server_sock.accept()
            with client_sock:
                # クライアントからオーディオプロパティを受信
                settings_list = client_sock.recv(256).decode('utf-8').split(",")
                FORMAT = int(settings_list[0])
                CHANNELS = int(settings_list[1])
                RATE = int(settings_list[2])
                CHUNK = int(settings_list[3])

                # オーディオ出力ストリーム生成
                # stream = audio.open(format=FORMAT,
                #                     channels=CHANNELS,
                #                     rate=RATE,
                #                     output=True,
                #                     frames_per_buffer=CHUNK)

                # ファイル出力定義
                # wave_f = wave.open(filepath, 'wb')
                # wave_f.setnchannels(1)
                # wave_f.setsampwidth(2)
                # wave_f.setframerate(16000)

                # メインループ
                while True:
                    # クライアントから音データを受信
                    data = client_sock.recv(CHUNK)
                    # ファイル出力処理
                    # wave_f.writeframes((data))

                    # 切断処理
                    if not data:
                        no_data = True
                        break

                    # オーディオ出力ストリームにデータ書き込み
                    # stream.write(data)
                    # ストリームをQueueに保存
                    queue.put(data)

        # 終了処理
        # stream.stop_stream()
        # stream.close()
        queue.put(None)
        audio.terminate()

class ParseTranscribeResultAndUploadToS3(TranscriptResultStreamHandler):
    def __init__(self, TranscriptResultStream, bucket_name, threshold=2):
        super().__init__(TranscriptResultStream)
        self.S3_CLIENT = boto3.client('s3')
        self.BUCKET_NAME = bucket_name
        self.THRESHOLD = threshold
        self.wite_partial = 0
        self.date_time = None
        self.translated_text = ''

    # S3にアップロード
    # def upload_to_s3(self, text):
    #     key = "origin/record_{}.txt".format(self.date_time)
    #     self.S3_CLIENT.put_object(Body=text, Bucket=self.BUCKET_NAME, Key=key)

    # 翻訳
    def translate_text(self, text):
        try:
            translate_resp = translate.translate_text(
                Text=text,
                SourceLanguageCode='en',
                TargetLanguageCode='ja'
            )
            return translate_resp.get('TranslatedText')
        except Exception as e:
            print(e)

    # DynamoDBにアップロード
    def upload_to_db(self, text):
        try:
            db_resp = table.put_item(
                Item={
                    'id': int(self.date_time[0:8]),
                    'date': int(self.date_time),
                    'origin': text,
                    'translated': self.translated_text,
                    'speaker': '',
                    'sid': ''
                }
            )
        except Exception as e:
            print(e)

    # 翻訳とDBにアップロード
    def translate_and_upload(self, text):
        self.translated_text = self.translate_text(text)
        self.upload_to_db(text)

    # 文字起こしの結果を抽出
    async def handle_transcript_event(self, transcript_event: TranscriptEvent):
        results = transcript_event.transcript.results
        # num_chars_printed = 0
        # interim_flush_counter = 0
        for result in results:
            if not self.date_time:
                self.date_time = datetime.now().strftime("%Y%m%d%H%M%S%f")
            transcript = result.alternatives[0].transcript
            # overwrite_chars = " " * (num_chars_printed - len(transcript))
            if result.is_partial:
                # 文字起こしの途中
                # sys.stdout.write(transcript + overwrite_chars + "\r")
                # sys.stdout.flush()
                # interim_flush_counter += 1

                # num_chars_printed = len(transcript)
                self.wite_partial += 1
                if self.wite_partial < self.THRESHOLD:
                    self.upload_to_db(transcript)
                else:
                    self.wite_partial = 0
                    self.translate_and_upload(text=transcript)
            else:
                # 文字起こしの結果が決定
                text = transcript # + overwrite_chars
                self.translate_and_upload(text)
                self.translated_text = ''
                self.date_time = None
                self.wite_partial = 0
                # print(text)
                # num_chars_printed = 0

class StreamingClientWrapper:
    def __init__(self, region, lang, sample_rate, bucket_name):
        self.REGION = region
        self.LANG = lang
        self.SAMPLE_RATE = sample_rate
        self.BUCKET_NAME = bucket_name

    async def start_listen(self):
        # AWSクライアント生成 (リージョン)
        speech_client = TranscribeStreamingClient(region=self.REGION)
        # AWS文字起こしの準備
        stream = await speech_client.start_stream_transcription(
            language_code=self.LANG,
            media_sample_rate_hz=self.SAMPLE_RATE,
            media_encoding="pcm",
            show_speaker_label=True,
        )
        # 文字起こし
        async def write_chunks(stream):
            global queue, no_data
            while not queue.empty() or not no_data:
                await stream.input_stream.send_audio_event(audio_chunk=queue.get())
            await stream.input_stream.end_stream()

        handler = ParseTranscribeResultAndUploadToS3(stream.output_stream, bucket_name=self.BUCKET_NAME)
        await asyncio.gather(write_chunks(stream), handler.handle_events())

if __name__ == '__main__':
    mss_server = SoundStreamServer("localhost", 12345)
    wrapper = StreamingClientWrapper(region, "en-US", 16000, bucket_name)

    loop = asyncio.get_event_loop()
    mss_server.start()
    loop.run_until_complete(wrapper.start_listen())
    mss_server.join()
    loop.close()


import os
import boto3

dynamo_client = boto3.client(
        'dynamodb',
        endpoint_url='http://dynamodb:8000',
        region_name=os.environ.get('AWS_DEFAULT_REGION', 'us-west-2'),
        aws_access_key_id=os.environ.get('AWS_ACCESS_KEY_ID', ''),
        aws_secret_access_key=os.environ.get('AWS_SECRET_ACCESS_KEY', '')
    )

def get_items():
    return dynamo_client.scan(
        TableName=os.environ.get('TABLE_NAME', 'TestTable')
    )


import torch.nn as nn
import torch
from transformers import CLIPModel
from torchvision import transforms

class VisionEncoder(nn.Module):
    def __init__(self, pretrained_model: str = "flaviagiammarino/pubmed-clip-vit-base-patch32"):
        super(VisionEncoder, self).__init__()

        # Load the CLIP model and tokenizer
        self.model = CLIPModel.from_pretrained(pretrained_model)
        self.transform = self.get_image_transforms()

    def get_image_transforms(self):
        """Defines the image preprocessing pipeline."""
        return transforms.Compose([
            transforms.Resize((224, 224)),
            transforms.ToTensor()])

    def forward(self, images):
        """Extract features from images."""
        images = [self.transform(image) for image in images]
        images = torch.stack(images, dim=0)
        features = self.model.encode_image(images)
        return features

if __name__ == '__main__':
    encoder = VisionEncoder()
    from PIL import Image
    sample_image = Image.open("./data/img/synpic676.jpg")
    features = encoder([sample_image])
    print(features.shape)  # Expected: torch.Size([1, 512])


import os
import os.path as osp

import cv2
import numpy as np
import vispy
from transforms3d.axangles import axangle2mat
from transforms3d.quaternions import quat2mat
from vispy import app, gloo

# import torch
# import copy
import OpenGL.GL as gl
from lib.render_vispy.frustum import Camera3D
from lib.render_vispy.model3d import Model3D, load_models  # noqa

os.environ["PYOPENGL_PLATFORM"] = "egl"

cur_dir = osp.dirname(osp.abspath(__file__))

# app backends: glfw, pyglet, egl
# gl backends: gl2, pyopengl2, gl+
app_backend = "egl"
gl_backend = "gl2"  # "pyopengl2"  # speed: 'gl+' < 'gl2' < 'pyopengl2'
vispy.use(app=app_backend, gl=gl_backend)
print("vispy uses app: {}, gl: {}".format(app_backend, gl_backend))

def shader_from_path(shader_filename):
    shader_path = osp.join(cur_dir, "./shader", shader_filename)
    assert osp.exists(shader_path)
    with open(shader_path, "r") as f:
        return f.read()

def singleton(cls):
    instances = {}

    def get_instance(size, cam, model_paths=None, scale_to_meter=1.0, gpu_id=None):
        if cls not in instances:
            instances[cls] = cls(size, cam, model_paths, scale_to_meter, gpu_id)
        return instances[cls]

    return get_instance

@singleton  # Don't throw GL context into trash when having more than one Renderer instance
class Renderer(app.Canvas):
    """
    NOTE: internally convert RGB to BGR
    """

    def __init__(self, size, cam, model_paths=None, scale_to_meter=1.0, gpu_id=None):
        """
        size: (width, height)
        """
        app.Canvas.__init__(self, show=False, size=size)
        width, height = size
        self.height = height
        self.width = width
        self.shape = (height, width)  # height, width

        # OpenGL is right-hand with (x+ right, y+ up and z- is forward)
        # OpenCV is right-hand with (x+ right, y- up and z+ is forward)
        # We define everything in OUR left-hand global system (x+ is right, y+ is up, z+ is forward)
        # We therefore must flip Y for OpenCV and Z for OpenGL for every operation
        self.opengl_zdir_neg = np.eye(4, dtype=np.float32)
        # self.opengl_zdir_neg[2, 2] = -1
        self.opengl_zdir_neg[1, 1], self.opengl_zdir_neg[2, 2] = -1, -1

        self.set_cam(cam)
        self.setup_views()

        # Set up shader programs
        # fmt: off
        _vertex_code_pointcloud = shader_from_path("point_cloud.vs")
        _fragment_code_pointcloud = shader_from_path("point_cloud.frag")  # varying

        _vertex_code_colored = shader_from_path("colored.vs")
        _fragment_code_colored = shader_from_path("colored.frag")

        # use colored vertex shader
        _fragment_code_bbox = shader_from_path("bbox.frag")

        _vertex_code_textured = shader_from_path("textured.vs")
        _fragment_code_textured = shader_from_path("textured.frag")

        _vertex_code_background = shader_from_path("background.vs")
        _fragment_code_background = shader_from_path("background.frag")
        self.program_pcl = gloo.Program(_vertex_code_pointcloud, _fragment_code_pointcloud)
        self.program_col = gloo.Program(_vertex_code_colored, _fragment_code_colored)
        self.program_bbox = gloo.Program(_vertex_code_colored, _fragment_code_bbox)
        self.program_tex = gloo.Program(_vertex_code_textured, _fragment_code_textured)
        self.program_bg = gloo.Program(_vertex_code_background, _fragment_code_background)
        # fmt: on

        # Texture where we render the color/depth and its FBO
        self.col_tex = gloo.Texture2D(shape=self.shape + (3,))
        self.fbo = gloo.FrameBuffer(self.col_tex, gloo.RenderBuffer(self.shape))
        self.fbo.activate()
        # gloo.set_state(depth_test=True, blend=False, cull_face=True)
        gloo.set_state(depth_test=True, blend=False, cull_face=False)
        gl.glEnable(gl.GL_LINE_SMOOTH)
        # gl.glDisable(gl.GL_LINE_SMOOTH)
        gloo.set_clear_color((0.0, 0.0, 0.0))
        gloo.set_viewport(0, 0, *self.size)

        # Set up background render quad in NDC
        quad = [[-1, -1], [1, -1], [1, 1], [-1, 1]]
        tex = [[0, 1], [1, 1], [1, 0], [0, 0]]
        vertices_type = [
            ("a_position", np.float32, 2),
            ("a_texcoord", np.float32, 2),
        ]
        collated = np.asarray(list(zip(quad, tex)), vertices_type)
        self.bg_vbuffer = gloo.VertexBuffer(collated)
        self.bg_ibuffer = gloo.IndexBuffer([0, 1, 2, 0, 2, 3])

        self.models = None
        if model_paths is not None:
            self._load_models(model_paths, scale_to_meter=scale_to_meter)

    def _load_models(self, model_paths, scale_to_meter=1.0):
        self.models = load_models(model_paths, scale_to_meter=scale_to_meter)

    def set_cam(self, cam, clip_near=0.1, clip_far=100.0):
        self.cam = cam
        self.clip_near = clip_near
        self.clip_far = clip_far
        self.mat_proj = self.projective_matrix(cam, 0, 0, self.shape[1], self.shape[0], clip_near, clip_far)

    def clear(self, color=True, depth=True):
        gloo.clear(color=color, depth=depth)

    def setup_views(self):
        self.view = dict()

        self.view["back"] = np.eye(4)
        self.view["back"][:3, :3] = axangle2mat(axis=[1, 0, 0], angle=15 * np.pi / 180)
        self.view["back"][:3, 3] = [0, -2.0, -3.25]

        self.view["center"] = np.eye(4)

        self.view["front"] = np.eye(4)
        self.view["front"][:3, :3] = axangle2mat(axis=[1, 0, 0], angle=9 * np.pi / 180)
        self.view["front"][:3, 3] = [0, 0, 3.25]

        self.view["show"] = np.eye(4)
        self.view["show"][:3, :3] = axangle2mat(axis=[1, 0, 0], angle=5 * np.pi / 180) @ axangle2mat(
            axis=[0, 1, 0], angle=-15 * np.pi / 180
        )
        self.view["show"][:3, 3] = [-3.5, -1, -5]
        self.used_view = "center"

    def finish(self, only_color=False, to_255=False):
        # NOTE: the colors in Model3D were converted into BGR, so the rgb loaded here is BGR
        im = gl.glReadPixels(0, 0, self.size[0], self.size[1], gl.GL_RGB, gl.GL_FLOAT)
        # Read buffer and flip X
        rgb = np.copy(np.frombuffer(im, np.float32)).reshape(self.shape + (3,))[::-1, :]
        if to_255:
            rgb = (rgb * 255 + 0.5).astype(np.uint8)
        if only_color:
            return rgb

        im = gl.glReadPixels(
            0,
            0,
            self.size[0],
            self.size[1],
            gl.GL_DEPTH_COMPONENT,
            gl.GL_FLOAT,
        )
        # Read buffer and flip X
        dep = np.copy(np.frombuffer(im, np.float32)).reshape(self.shape + (1,))[::-1, :]

        # Convert z-buffer to depth map
        mult = (self.clip_near * self.clip_far) / (self.clip_near - self.clip_far)
        addi = self.clip_far / (self.clip_near - self.clip_far)
        bg = dep == 1
        dep = mult / (dep + addi)
        dep[bg] = 0
        return rgb, np.squeeze(dep)

    def compute_rotation(self, eye_point, look_point):
        up = [0, 1, 0]
        if eye_point[0] == 0 and eye_point[1] != 0 and eye_point[2] == 0:
            up = [0, 0, -1]
        rot = np.zeros((3, 3))
        rot[2] = look_point - eye_point
        rot[2] /= np.linalg.norm(rot[2])
        rot[0] = np.cross(rot[2], up)
        rot[0] /= np.linalg.norm(rot[0])
        rot[1] = np.cross(rot[0], -rot[2])
        return rot.T

    def _validate_pose(self, pose, rot_type="mat"):
        if rot_type == "mat":
            res = pose
            if pose.shape[0] == 3:
                res = np.concatenate(
                    (
                        pose,
                        np.array([0, 0, 0, 1], dtype=np.float32).reshape(1, 4),
                    ),
                    axis=0,
                )
        elif rot_type == "quat":
            res = np.eye(4)
            res[:3, :3] = quat2mat(pose[:4])
            res[:3, 3] = pose[4:7]
        else:
            raise ValueError(f"wrong rot_type: {rot_type}")
        return res  # 4x4

    def draw_detection_boundingbox(
        self,
        pose,
        extents,
        view="center",
        is_gt=False,
        thickness=1.5,
        centroid=0,
        rot_type="mat",
    ):
        """
        centroid: [0,0,0]
        """
        assert view in ["front", "top", "back", "show", "center"]
        pose = self._validate_pose(pose, rot_type=rot_type)
        xsize, ysize, zsize = extents
        # fmt: off
        bb = np.asarray([[-xsize / 2, ysize / 2, zsize / 2], [xsize / 2, ysize / 2, zsize / 2],
                         [-xsize / 2, -ysize / 2, zsize / 2], [xsize / 2, -ysize / 2, zsize / 2],
                         [-xsize / 2, ysize / 2, -zsize / 2], [xsize / 2, ysize / 2, -zsize / 2],
                         [-xsize / 2, -ysize / 2, -zsize / 2], [xsize / 2, -ysize / 2, -zsize / 2]])
        # Set up rendering data
        bb += centroid
        if is_gt:
            colors = [[0, 0, 1], [0, 0, 1], [0, 0, 1], [0, 0, 1], [0, 1, 1], [0, 1, 1], [0, 1, 1], [0, 1, 1]]
        else:
            colors = [[0, 1, 0], [0, 1, 0], [0, 1, 0], [0, 1, 0], [1, 1, 0], [1, 1, 0], [1, 1, 0], [1, 1, 0]]
        # fmt: on
        indices = [
            0,
            1,
            0,
            2,
            3,
            1,
            3,
            2,
            4,
            5,
            4,
            6,
            7,
            5,
            7,
            6,
            0,
            4,
            1,
            5,
            2,
            6,
            3,
            7,
        ]

        vertices_type = [
            ("a_position", np.float32, 3),
            ("a_color", np.float32, 3),
        ]
        collated = np.asarray(list(zip(bb, colors)), vertices_type)

        self.program_bbox.bind(gloo.VertexBuffer(collated))

        # Flip from our system and .T since OpenGL is column-major
        self.program_bbox["u_model"] = (self.opengl_zdir_neg.dot(pose)).T
        self.program_bbox["u_view"] = self.view[view].T
        self.program_bbox["u_projection"] = self.mat_proj

        gloo.set_line_width(width=thickness)
        self.program_bbox.draw("lines", gloo.IndexBuffer(indices))
        gloo.set_line_width(width=1.0)

    def draw_camera(
        self,
        pose=None,
        color=[0, 1, 0],
        scaler=1.0,
        view="center",
        rot_type="mat",
    ):
        if pose is None:
            pose = np.eye(4)
        else:
            pose = self._validate_pose(pose)

        assert view in ["front", "top", "back", "show"]

        cam = Camera3D(color=color, scaler=scaler)

        # View matrix (transforming the coordinate system from OpenCV to OpenGL camera space)
        # Flip from our system and .T since OpenGL is column-major
        mv = (self.opengl_zdir_neg.dot(pose)).T

        self.program_bbox.bind(cam.vertex_buffer)

        self.program_bbox["u_model"] = mv
        self.program_bbox["u_view"] = self.view[view].T
        self.program_bbox["u_projection"] = self.mat_proj

        gloo.set_line_width(width=2.5)
        self.program_bbox.draw("lines", cam.index_buffer)
        gloo.set_line_width(width=1.0)

    def draw_pointcloud(self, points, colors=None, s_color=None, radius=1.0, view="center"):

        assert view in ["center", "front", "top", "back", "show"]

        points = np.copy(points)

        if colors is None:
            if s_color is None:
                colors = np.asarray(
                    np.ones((points.shape[0], 1)) * [1, 0, 0, 1],
                    dtype=np.float32,
                )
            else:
                colors = np.asarray(
                    np.ones((points.shape[0], 1)) * [1, 0, 0, 1],
                    dtype=np.float32,
                )

        radius = np.ones((points.shape[0]), dtype=np.float32) * radius
        # fmt: off
        data = np.zeros(points.shape[0], [("a_position", np.float32, 3), ("a_bg_color", np.float32, 4),
                                          ("a_fg_color", np.float32, 4), ("a_size", np.float32, 1)])
        # fmt: on

        data["a_position"] = points
        data["a_size"] = radius
        data["a_fg_color"] = 0, 0, 0, 0.5
        data["a_fg_color"] = colors

        self.program_pcl.bind(gloo.VertexBuffer(data))
        self.program_pcl["u_linewidth"] = 0.75
        self.program_pcl["u_antialias"] = 1.00
        self.program_pcl["u_model"] = self.opengl_zdir_neg.dot(np.eye(4)).T
        self.program_pcl["u_view"] = self.view[view].T
        self.program_pcl["u_projection"] = self.mat_proj

        self.program_pcl.draw("points")

    def draw_background(self, image):
        """bgr image."""
        self.program_bg["u_tex"] = gloo.Texture2D(image)
        self.program_bg.bind(self.bg_vbuffer)
        self.program_bg.draw("triangles", self.bg_ibuffer)
        gloo.clear(color=False, depth=True)  # Clear depth

    def draw_model(
        self,
        model_or_id,
        pose,
        ambient=0.5,
        specular=0,
        shininess=1,
        light_dir=(0, 0, -1),
        light_col=(1, 1, 1),
        view="center",
        rot_type="mat",
    ):
        """
        pose: 4x4
        """
        assert view in ["front", "top", "back", "center", "show"]
        pose = self._validate_pose(pose, rot_type=rot_type)
        # View matrix (transforming the coordinate system from OpenCV to OpenGL camera space)
        # Flip from our system and .T since OpenGL is column-major
        m = (self.opengl_zdir_neg.dot(pose)).T

        if isinstance(model_or_id, int):
            # how to avoid re-binding for existing models???
            assert self.models is not None, self.models
            model = self.models[model_or_id]
        else:
            model = model_or_id

        used_program = self.program_col
        if model.texcoord is not None:
            used_program = self.program_tex
            used_program["u_tex"] = model.texture

        used_program.bind(model.vertex_buffer)
        used_program["u_view"] = self.view[view].T
        used_program["u_projection"] = self.mat_proj
        used_program["u_light_dir"] = light_dir
        used_program["u_light_col"] = light_col
        used_program["u_ambient"] = ambient
        used_program["u_specular"] = specular
        used_program["u_shininess"] = shininess

        used_program["u_model"] = m

        used_program.draw("triangles", model.index_buffer)

    def show_scene(self, points, colors, models, poses):
        angular_err, trans_err = np.inf, np.inf

        camera_locations = np.asarray([[7.0, 7.0, 10.0]])
        lookat_locations = np.asarray([[0.0, 0.0, 20.0]])

        # for pose in poses:
        #    lookat = pose[:3, 3].copy()
        #    position = lookat.copy()
        #    position[0] = 0.

        #    camera_locations.append(position)
        #    lookat_locations.append(lookat)

        view = np.eye(4)
        steps = 300

        for path_idx in range(len(camera_locations)):
            cam_loc, lookat_loc = (
                camera_locations[path_idx],
                lookat_locations[path_idx],
            )

            t_start = np.copy(view[:3, 3])
            t_end = cam_loc

            for i in range(steps):

                view[:3, :3] = np.eye(3)

                eye_pos = t_start + ((t_end - t_start) * (i / steps))

                rot = self.compute_rotation(eye_pos, lookat_loc).T
                view[:3, :3] = rot
                view[:3, 3] = -rot @ eye_pos

                print(view)

                self.view["show"] = view.copy()

                flip = np.eye(4)
                self.view["show"] = flip.dot(self.view["show"])

                self.clear()
                self.draw_pointcloud(points, colors, view="show")

                for moodel, pose in zip(models, poses):
                    self.draw_model(moodel, pose, view="show")

                cv2.imshow("show", self.finish()[0])
                cv2.waitKey(10)

    def projective_matrix(self, cam, x0, y0, w, h, nc, fc):

        q = -(fc + nc) / float(fc - nc)
        qn = -2 * (fc * nc) / float(fc - nc)

        # Draw our images upside down, so that all the pixel-based coordinate systems are the same
        # fmt: off
        proj = np.array([
            [2 * cam[0, 0] / w, -2 * cam[0, 1] / w, (-2 * cam[0, 2] + w + 2 * x0) / w, 0],
            [0, 2 * cam[1, 1] / h, (2 * cam[1, 2] - h + 2 * y0) / h, 0],
            [0, 0, q, qn],  # This row is standard glPerspective and sets near and far planes
            [0, 0, -1, 0]
        ])
        # fmt: on

        # Compensate for the flipped image
        return proj.T

if __name__ == "__main__":
    from transforms3d.axangles import axangle2mat
    import time
    from lib.vis_utils.image import vis_image_mask_bbox_cv2
    from tqdm import tqdm
    import matplotlib.pyplot as plt

    import ref

    ref_key = "lm_full"
    data_ref = ref.__dict__[ref_key]

    classes = data_ref.objects
    model_paths = data_ref.model_paths
    # models = load_models()

    cam = data_ref.camera_matrix
    width = data_ref.width
    height = data_ref.height

    obj_ids = [i for i in range(len(model_paths))]

    R1 = axangle2mat((1, 0, 0), angle=0.5 * np.pi)
    R2 = axangle2mat((0, 0, 1), angle=-0.7 * np.pi)
    R = np.dot(R1, R2)
    t = np.array([0, 0, 0.7], dtype=np.float32)
    pose = np.hstack([R, t.reshape((3, 1))])
    pose1 = np.hstack([R, 0.1 + t.reshape((3, 1))])
    pose2 = np.hstack([R, t.reshape((3, 1)) - 0.1])
    pose3 = np.hstack([R, t.reshape((3, 1)) - 0.05])
    pose4 = np.hstack([R, t.reshape((3, 1)) + 0.05])

    # tensor_kwargs = {'device': torch.device('cuda'), 'dtype': torch.float32}
    # image_tensor = torch.empty((height, width, 4), **tensor_kwargs).detach()
    ren = Renderer(
        size=(width, height),
        cam=cam,
        model_paths=model_paths,
        scale_to_meter=data_ref.vertex_scale,
    )

    # rendering
    runs = 0
    t_render = 0
    for j in tqdm(range(200)):
        for obj_id, cls_name in enumerate(classes):
            t0 = time.perf_counter()

            poses = [pose, pose1, pose2, pose3, pose4]
            obj_ids = [obj_id, obj_id, obj_id, obj_id, obj_id]
            # poses = [pose]
            # obj_ids = [obj_id]
            ren.clear()
            # ren.draw_background(background)
            for i in range(len(poses)):
                # cur_model = models[obj_ids[i]]
                cur_model = ren.models[obj_ids[i]]
                ren.draw_model(obj_ids[i], poses[i])
                ren.draw_detection_boundingbox(
                    poses[i],
                    [cur_model.xsize, cur_model.ysize, cur_model.zsize],
                )
            im, depth = ren.finish()
            # ren.finish(image_tensor=image_tensor)

            # im = (im.cpu().numpy() + 0.5).astype(np.uint8)
            t_render += time.perf_counter() - t0
            runs += 1
            if False:
                fig = plt.figure(frameon=False, dpi=200)
                plt.subplot(1, 2, 1)
                # im = (image_tensor[:, :, :3].cpu().numpy() + 0.5).astype('uint8')
                plt.imshow(im[:, :, [2, 1, 0]])  # rgb
                plt.axis("off")
                plt.title("{} color".format(cls_name))

                plt.subplot(1, 2, 2)
                plt.imshow(depth)
                plt.axis("off")
                plt.title("{} depth".format(cls_name))

                plt.show()
    print("{}s {}fps".format(t_render / runs, runs / t_render))
    # 5 objs: 0.01251343576113383s 79.91410345557973fps
    # 1 obj:  0.00796224382718404s 125.59273763833781fps


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

from sys import argv, exit
from subprocess import Popen, PIPE
from os import path, listdir, sep, name
from datetime import date, datetime, time, timedelta
from PyQt5 import QtWidgets, QtGui, QtCore, QtSql

class MyWindows(QtWidgets.QMainWindow):
    def __init__(self):
        super().__init__()
        self.zandronum_path_string = QtWidgets.QLineEdit()
        if (name == 'posix'):
            self.zandronum_path_string.setText(Popen(['which zandronum'], stdout=PIPE, shell=True).communicate()[0].decode())
        #
        self.cbx_select_iwad = QtWidgets.QComboBox(self)
        self.cbx_pk3s_menu = QtWidgets.QMenu(self)
        #
        self.chbx_networking_game = QtWidgets.QCheckBox()
        self.edit_server = QtWidgets.QLineEdit('ice2heart.com')
        self.edit_server_port = QtWidgets.QLineEdit('10666')
        #
        self.info = QtWidgets.QTextEdit()
        # Список pk3-файлов
        self.pk3s = []
        #
        self.db = self.dbInit()
        self.serverModel = QtSql.QSqlTableModel(self, self.db)
        #
        self.initUI()
        self.cbx_populate()
        # self.saveOptionsload()
        self.makeInfo()

    def initUI(self):
        central_widget = QtWidgets.QWidget(self)
        self.setCentralWidget(central_widget)
        central_widget_grid_layout = QtWidgets.QGridLayout()
        central_widget.setLayout(central_widget_grid_layout)
        #
        file_group = QtWidgets.QGroupBox()
        file_group.setFixedSize(380, 150)
        file_group_layout = QtWidgets.QGridLayout()
        #
        self.zandronum_path_string.setFixedHeight(25)
        btn_select_zandronum_path = QtWidgets.QPushButton("..")
        btn_select_zandronum_path.setFixedSize(25, 25)
        btn_select_zandronum_path.setToolTip("Указать путь к бинарнику Zandronum")
        btn_select_zandronum_path.pressed.connect(lambda: self.openZandronumBinPath())
        # Выбор wad'ов
        self.cbx_select_iwad.currentTextChanged.connect(lambda: self.fileSelection("wad"))
        self.cbx_select_iwad.setFixedSize(225, 25)
        # Выбор pk3-файлов
        cbx_select_pk3 = QtWidgets.QToolButton(self)
        cbx_select_pk3.setMenu(self.cbx_pk3s_menu)
        cbx_select_pk3.setPopupMode(QtWidgets.QToolButton.InstantPopup)
        cbx_select_pk3.triggered.connect(lambda cbx_select_pk3: self.fileSelection("pk3", cbx_select_pk3))
        cbx_select_pk3.setFixedSize(225, 25)
        #
        file_group_layout.addWidget(QtWidgets.QLabel("Путь к zandronum:"), 0, 0)
        file_group_layout.addWidget(self.zandronum_path_string, 1, 0, 1, 2)
        file_group_layout.addWidget(btn_select_zandronum_path, 1, 2)
        file_group_layout.addWidget(QtWidgets.QLabel("iwad-файл:"), 2, 0)
        file_group_layout.addWidget(self.cbx_select_iwad, 2, 1)
        file_group_layout.addWidget(QtWidgets.QLabel("pk3-файл(ы):"), 3, 0)
        file_group_layout.addWidget(cbx_select_pk3, 3, 1)
        # Сеть
        network_group = QtWidgets.QGroupBox()
        network_group_layout = QtWidgets.QGridLayout()
        #
        self.chbx_networking_game.setText("Сетевая игра")
        self.chbx_networking_game.setChecked(True)
        self.chbx_networking_game.stateChanged.connect(lambda: self.networkingGame())
        #
        self.edit_server.setFixedSize(220, 25)
        btn_add_server = QtWidgets.QPushButton()
        btn_add_server.setText("+")
        btn_add_server.setToolTip("Сохранить сервер")
        btn_add_server.setFixedSize(25, 25)
        btn_add_server.pressed.connect(lambda: self.db_queryServer())
        # Таблица с сохранёнными серверами
        self.serverModel.setEditStrategy(QtSql.QSqlTableModel.OnFieldChange)
        self.serverModel.setTable('servers')
        self.serverModel.select()
        # self.serverModel.removeColumn(0)
        # self.serverModel.setHeaderData(0, QtCore.Qt.Horizontal, "ID")
        self.serverModel.setHeaderData(1, QtCore.Qt.Horizontal, "Сервер")
        self.serverModel.setHeaderData(2, QtCore.Qt.Horizontal, "Порт")
        tbl_servers = QtWidgets.QTableView()
        tbl_servers.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Stretch)
        tbl_servers.verticalHeader().hide()
        tbl_servers.setSelectionMode(QtWidgets.QTableView.SingleSelection)
        tbl_servers.setSelectionBehavior(QtWidgets.QTableView.SelectRows)
        tbl_servers.setEditTriggers(QtWidgets.QTableView.NoEditTriggers)
        tbl_servers.setAlternatingRowColors(True)
        tbl_servers.setModel(self.serverModel)
        tbl_servers.setColumnHidden(0, True)
        tbl_servers.doubleClicked.connect(lambda: self.db_getSaveServer(tbl_servers.currentIndex())) # Двойной клик по таблице (выбор сохраненного сервера)
        QtWidgets.QShortcut(QtCore.Qt.Key_Delete, tbl_servers, activated=lambda: self.db_queryServer(1, tbl_servers.currentIndex())) # Удаление записи из БД по Delete
        #
        network_group_layout.addWidget(self.chbx_networking_game, 0, 0)
        network_group_layout.addWidget(QtWidgets.QLabel("Сервер"), 1, 0)
        network_group_layout.addWidget(self.edit_server, 2, 0)
        network_group_layout.addWidget(QtWidgets.QLabel("Порт"), 1, 1)
        network_group_layout.addWidget(self.edit_server_port, 2, 1)
        network_group_layout.addWidget(btn_add_server, 2, 2)
        #
        network_group_layout.addWidget(QtWidgets.QLabel("Сохраненные сервера"), 3, 0)
        network_group_layout.addWidget(tbl_servers, 4, 0, 1, 3)
        #
        rungame_group = QtWidgets.QGroupBox()
        rungame_group_layout = QtWidgets.QGridLayout()
        # Информация
        info_group = QtWidgets.QGroupBox()
        info_group_layout = QtWidgets.QGridLayout()
        #
        info_group_layout.addWidget(self.info)
        info_group.setLayout(info_group_layout)
        # Кнопка запуска
        btn_rungame = QtWidgets.QPushButton()
        btn_rungame.setText("Запустить игру!")
        btn_rungame.pressed.connect(lambda: self.runGame())
        rungame_group_layout.addWidget(btn_rungame)
        #
        file_group.setLayout(file_group_layout)
        network_group.setLayout(network_group_layout)
        rungame_group.setLayout(rungame_group_layout)
        #
        central_widget_grid_layout.addWidget(file_group, 0, 0)
        central_widget_grid_layout.addWidget(network_group, 1, 0)
        central_widget_grid_layout.addWidget(info_group, 2, 0)
        central_widget_grid_layout.addWidget(rungame_group, 3, 0)
        #
        self.setWindowTitle("ZLauncher - Zandronum launcher ver. 0.1")
        self.setFixedSize(400, 600)
        self.setCenter()
        self.show()

    # Ручками указать путь к Zandronum
    def openZandronumBinPath(self):
        filename = QtWidgets.QFileDialog().getOpenFileName(self, 'Найти бинарь Zandronum\'а', path.dirname(path.realpath(__file__)))[0]
        if ("zandronum" in filename.lower()):
            self.zandronum_path_string.setText(filename)
        elif (len(filename) < 1):
            pass
        else:
            self.message("Не верное имя файла!\n Укажите путь к \"zandorum\".")

    # Центрирование окна
    def setCenter(self):
        qr = self.frameGeometry()
        cp = QtWidgets.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    # Заполнение ComboBox'ов файлами
    def cbx_populate(self):
        try:
            for i in map(path.splitext, listdir(path.dirname(path.realpath(__file__))+sep+"wads")):
                if (i[1].upper() == ".WAD"):
                    self.cbx_select_iwad.addItem(i[0]+i[1])
                elif (i[1].upper() == ".PK3"):
                    action = self.cbx_pk3s_menu.addAction(i[0]+i[1])
                    action.setCheckable(True)
            self.cbx_select_iwad.setCurrentIndex(0)
        except:
            self.message("Отсутствует каталог с wad-файлами!")

    # Формирование списка файлов
    def fileSelection(self, file, selected = ""):
        if file != "wad" and selected != "":
            if (selected.isChecked()):
                self.pk3s.append(selected.text())
            else:
                self.pk3s.remove(selected.text())
        self.makeInfo()

    # Контроль сетевой игры
    def networkingGame(self):
        if self.chbx_networking_game.isChecked():
            self.edit_server.setEnabled(True)
            self.edit_server_port.setEnabled(True)
        else:
            self.edit_server.setDisabled(True)
            self.edit_server_port.setDisabled(True)
        self.makeInfo()

    # Выбор сохраненного сервера
    def db_getSaveServer(self, currentIndex):
        self.edit_server.setText(str(self.serverModel.record(currentIndex.row()).value(1)))
        self.edit_server_port.setText(str(self.serverModel.record(currentIndex.row()).value(2)))

    # Сохранить сервер в БД или удалить из БД
    def db_queryServer(self, delete = 0, currentIndex = 0):
        query = QtSql.QSqlDatabase(self.db)
        if delete == 1:
            query.exec_("DELETE FROM `servers` WHERE `id` = "+str(self.serverModel.record(currentIndex.row()).value(0)))
            self.message("Сервер удалён.")
        else:
            query.exec_("INSERT INTO `servers`(`host`, `port`) VALUES('"+self.edit_server.text()+"', '"+self.edit_server_port.text()+"')")
            self.message("Сервер добавлен.")
        self.serverModel.select()

    # Инициализация БД
    def dbInit(self):
        dbfile = path.dirname(path.realpath(__file__))+sep+"zlauncher.db"
        db = QtSql.QSqlDatabase.addDatabase('QSQLITE')
        db.setDatabaseName(dbfile)
        if not db.open():
                self.message("Ошибка инициализации БД!")
                return(False)
        if (path.getsize(dbfile) <= 0):
            query = QtSql.QSqlQuery(db)
            query.exec_("CREATE TABLE `servers`(`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `host` VARCHAR(50) NOT NULL, `port` INTEGER(5) NOT NULL)")
            query.exec_("INSERT INTO `servers`(`host`, `port`) VALUES('ice2heart.com', '10666')")
            query.exec_("CREATE TABLE `options`(`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `path` VARCHAR(255), `iwad` VARCHAR(50), `pk3` VARCHAR(50), `network` BOOLEAN, `host` VARCHAR(50), `port` INTEGER(5))")
        return(db)

    # Информация о выбранных компонентах
    def makeInfo(self):
        if self.chbx_networking_game.isChecked():
            server = "Сервер: "+self.edit_server.text()+"  : "+self.edit_server_port.text()
        else:
            server = ""
        self.info.setText("iwad: "+self.cbx_select_iwad.currentText()+
            "
pk3: "+", ".join(self.pk3s)+"
"+server)

    # Формирование параметров запуска
    def makeRunstring(self):
        if len(self.zandronum_path_string.text()) <= 0:
            self.message("На компьютере не обнаружен Zandronum!\n Укажите путь к исполняемому файлу Zandronum.")
            runstring = 0
            return(runstring)
        path_to_wads=path.dirname(path.realpath(__file__))+sep+"wads"+sep
        runstring = str(self.zandronum_path_string.text()).strip() + " "
        if (len(self.cbx_select_iwad.currentText()) > 0):
            runstring += "-iwad " + path_to_wads + self.cbx_select_iwad.currentText() + " "
        else:
            self.message("Отсутствует iwad-фалй!")
            runstring = 0
        if (len(self.pk3s) > 0):
            runstring = runstring + "-file "
            for i in self.pk3s:
                runstring += path_to_wads+i+" "
        if self.chbx_networking_game.isChecked():
            if len(self.edit_server.text()) > 1 and len(self.edit_server_port.text()) > 1:
                runstring += "+connect " + self.edit_server.text().strip() + " -port " + self.edit_server_port.text().strip()
            else:
                self.message("Укажите сервер и порт.")
                runstring = 0
        #
        if (runstring != 0):
            return(runstring)

    # Сохранение и восстановление параметров
    def saveOptionsload(self, runstring = "", save = 1):
        if (save == 1):
            import re
            print(re.split("(-iwad|-file|\+connect)", runstring))
            # rs = runstring.split(' ')
            # zp = rs.pop(0)
            # rs.pop(0)
            # iwad = rs.pop(0).split(sep)[-1]
            # rs.pop(0)
            # pk3 = []
            # server = ""
            # port = ""

            # # for i in (x for x in rs if x != "+connect"):
            # for i in rs:
            #     if i != "+connect":
            #         print(i)
            #     else:
            #         break

    # Запуск игры
    def runGame(self):
        runstring = self.makeRunstring()
        if (runstring != 0):
            print(runstring)
            # self.saveOptionsload(runstring)
            Popen(runstring, shell=True)

    # Сообщения
    def message(self, msg):
        mb = QtWidgets.QMessageBox()
        mb.question(self, "Сообщение", msg, QtWidgets.QMessageBox.Ok)

if __name__ == '__main__':
    app = QtWidgets.QApplication(argv)
    w = MyWindows()
    exit(app.exec_())