from PyQt5 import QtWidgets, uic
from PyQt5.QtWidgets import QDialog
import sys
import os
import pickle
import math
import time
import SenderGBN

class Sender(QDialog):

    def __init__(self):
        super(Sender, self).__init__()
        uic.loadUi("Sender.ui", self)
        self.pushButton.clicked.connect(self.sent_pressed)
        # self.lineEdit_2.setText("192.168.10.166")
        # self.lineEdit.setText("5010")
        self.pack_size = 0
        self.pocket_lost = 0
        self.window_size = 0
        self.lineEdit_3.setText(os.path.dirname(sys.argv[0])+r'/COSC635_P2_DataSent.txt')

    def sent_pressed(self):
        self.pack_size = int(self.lineEdit_4.text())
        self.pocket_lost = int(self.lineEdit_5.text())
        if self.radioButton.isChecked():
            print("GBN sent")
            self.window_size = 4
        else:
            print("SAW sent")
            self.window_size = 1

        file = open(self.lineEdit_3.text(), 'r', encoding='utf8')
        total_pack = int(math.ceil(sys.getsizeof(file.read()) / self.pack_size))
        # making all the data package along with part number and total pack number
        i = 1
        all_msg = []
        with open(self.lineEdit_3.text(), 'r', encoding='utf8') as in_file:
            payload = in_file.read(self.pack_size)
            while payload:
                msg_pickle = pickle.dumps({"part": i, "total_pack": total_pack, "msg": payload})
                payload = in_file.read(self.pack_size)
                all_msg.append(msg_pickle)
                i += 1
        print(all_msg)
        start_time = time.time()
        client_1 = SenderGBN.ClientServer(
            self.pocket_lost, all_msg, self.window_size, self.lineEdit_2.text(), int(self.lineEdit.text()))
        client_1.client_sent_group_pack()
        client_1.close_socket()
        msgbox = QtWidgets.QMessageBox(self)
        msgbox.setWindowTitle("Summary")
        msgbox.setText(f"File transfer completed:\n"
                       f"Total time used: {round(time.time() - start_time, 4)} seconds \n"
                       f"Total package: {total_pack} \n"
                       f"The pack was lost: {client_1.connection_fail - 1} times. \n"
                       f"Package Lost rate: {self.pocket_lost}%\n"
                       f"Each package size: {self.pack_size} bytes")
        msgbox.exec()

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    qt_app = Sender()
    qt_app.show()
    sys._excepthook = sys.excepthook

    def exception_hook(exctype, value, traceback):
        print(exctype, value, traceback)
        sys.excepthook(exctype, value, traceback)
        sys.exit(1)

    sys.excepthook = exception_hook

    app.exec_()


from django.core.files.storage import Storage
from fdfs_client.client import Fdfs_client
from django.conf import settings

class FastDFSStorage(Storage):
    """自定义Django存储系统的类"""
    # 在创建client对象的时候，我们通过原始的/etc/fdfs/client.conf找不到conf'文件，所以我们需要奖这个文件复制到当前项目中
    #client = Fdfs_client('./client.conf')的存在 耦合性太强，所以仿照FileSystemStorage这个类的初始化方法

    def __init__(self,client_conf=None,server_ip=None):    # 初始化方法，外界可以数据，可以不穿，传入数据， 就用，不传入，用自己的
        if client_conf is None:
            client_conf = settings.CLIENT_CONF
        self.client_conf = client_conf

        if server_ip is None:
            server_ip = settings.SERVER_IP
        self.server_ip = server_ip

    def _open(self,name,mode='rb'):
        """读取文件时使用，此处是存储到fasfdfs，所以不需要逻辑"""
        pass
    def _save(self,name,coneten):
        """存储文件时，name表示要上传的文件的名字，content表示File类型的对象，read方法可以读取内容"""
        # 创建client对象
        client = Fdfs_client(self.client_conf)
        # 获取上传的内容
        filter_data = coneten.read()
        # client获取文件内容
        try:
            ret = client.upload_by_buffer(filter_data)
        except Exception as e:
            print(e)  # 方便自己做调试
            raise       # 抓获到什么异常，就展示什么异常
        # 判断是否上传成功   注意  Upload successed.  后面有个点  不要i忘了那个点
        if ret.get('Status') == 'Upload successed.':
            # 上传成功,读取file_id,完成存储到mysql
            file_id = ret.get('Remote file_id')
            # 如果运维当前在操作GoodsCategory模型类,那么我们的Storage会自动的把返回的file_id,存储到GoodsCategory模型类对应的字段中
            return file_id
        else:
            # 上传失败 # 把错误暴露出来
            raise Exception ('上传失败')

    # 因为我们所有逻辑是运用django将图片存储到fdfs中，所以我们要重写exists方法，
    # 在文档中有提到：如果提供的名称所引用的文件在文件系统中存在，则返回True，否则如果这个名称可用于新文件，返回False。
    # 所以我们要重写方法，让它永远false，这样才能保证可以将文件存到fdfs中，django中永远没有数据
    def exists(self, name):
        """判断是否存储数据，有True，没有False"""
        return False   #告诉django文件不存在，可以存储文件

    def url(self, name):
        """可以返回要下载的文件的全路径，提供用户下载时候使用的"""
    #   返回URL，通过它可以访问到name所引用的文件   如果要下载就可以调用url方法，可以得到全路径
    # name就是要下载的文件名字，将来会把从数据库中查询处理来的fil_id传入到url方法中
    # name == 'group1/M00/00/00/wKh9hVqWFo - AffzqAAV6GVaZsqU005.jpg'
    # http://192.168.125.133:8888/group1/M00/00/00/wKh9hVqWFo - AffzqAAV6GVaZsqU005.jpg
        return self.server_ip+name

    """
>>> from fdfs_client.client import Fdfs_client
>>> client = Fdfs_client('/etc/fdfs/client.conf')
>>> ret = client.upload_by_filename('test')
>>> ret
{'Group name':'group1','Status':'Upload successed.', 'Remote file_id':'group1/M00/00/00/
	wKjzh0_xaR63RExnAAAaDqbNk5E1398.py','Uploaded size':'6.0KB','Local file name':'test'
	, 'Storage IP':'192.168.243.133'}
        """


import requests
import telegram
import logging
import time
import configparser

# 配置日志记录器
logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[
        logging.FileHandler("info.log"),
        logging.StreamHandler()
    ]
)

file = 'config.ini'

# 创建配置文件对象
con = configparser.ConfigParser()

# 读取文件
con.read(file, encoding='utf-8')

# 获取所有section
config = dict(con.items('default'))
location = config['download_location']

base_url = "https://www.bing.com/"
download_url = "https://www.bing.com/hpwp/"
api_url = "https://www.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&nc=1612409408851&pid=hp&FORM=BEHPTB&uhd=1" \
          "&uhdwidth=3840&uhdheight=2160 "

r = requests.get(api_url)
image = r.json()["images"][0]
copyright = image["copyright"]
startdate = image["startdate"]
title = image['title']
wallpaper_file_name = startdate + '_' + title.replace(" ", "_") + '.jpeg'
logging.info('file_name:%s', wallpaper_file_name)

# 获取hash
hsh = image["hsh"]
# 获得图片预览链接
img_pc_url = base_url + image["url"]
# 获取原图下载地址
img_pc_download_url = download_url + hsh
# 拼接本地下载地址
imgPcLocation = location + hsh
# Markdown内容
caption = '[' + copyright + '](' + img_pc_url + ')'

logging.info('img_pc_url:%s', img_pc_url)
logging.info('img_pc_download_url:%s', img_pc_download_url)

# 开始请求下载图片
img_response = requests.get(img_pc_url)
img_pc = img_response.content
# 获得文件名
filename = "BingWallpaper-" + time.strftime("%Y-%m-%d", time.localtime()) + ".jpg"
img_pc_location = location + wallpaper_file_name

# 保存到本地
with open(img_pc_location, 'wb+') as img:
    img.write(img_pc)

with open(location + 'pc.jpg', 'wb+') as img:
    img.write(img_pc)

# 发送到telegram
telegram.send_photo(img_pc_location, caption)
# Telegram.sendDocument(imgMbLocation)
# Telegram.send_message(imgPcUrl, copyright)
# Telegram.sendDocument(imgPcLocation)

logging.info("success!")


import requests
import json, sys
from dewiki import parser

def wiki():
    if len(sys.argv) != 2:
        print("1 argument required")
    else:
        url = 'https://en.wikipedia.org/w/api.php'
        page = sys.argv[1].replace(" ", "_")
        PARAMS = {
            "action": "query",
            "titles": page,
            "format": "json",
            "prop" : "revisions",
            "rvprop" : "content",
            "redirects" : ""
                }
        req = requests.get(url=url, params= PARAMS)
        if req.ok != True:
            exit("Error" + req.status_code)
        revisions = json.loads(req.text)['query']["pages"]
        for a, val in revisions.items():
            rev = val.get('revisions')
            if rev is None:
                print("Information not found")
                exit(1)
        page_name = rev[0]['*']
        #res = dewiki.from_string(rev[0]['*'])
        res = parser.Parser().parse_string(page_name)
        with open(page+".wiki ", "w") as file:
            file.write(str(res))

if __name__ == '__main__':
    wiki()


import os
from werkzeug.contrib.fixers import ProxyFix
from flask import Flask, redirect, url_for, render_template
from flask_dance.contrib.google import make_google_blueprint, google
from raven.contrib.flask import Sentry
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
os.environ['OAUTHLIB_RELAX_TOKEN_SCOPE'] = '1'

app = Flask(__name__)
app.config['SECRET_KEY'] = 'mysecretkey'
blueprint = make_google_blueprint(client_id='236746006863-19jtqj68p0hkk9lf60eqkmt0i5s9fo09.apps.googleusercontent.com'
                                  , client_secret='gInPVAmZFZKpCDMOosNjAEZd', offline=True,scope=['profile', 'email'])
app.register_blueprint(blueprint,url_prefix='/login')

@app.route('/')
def index():
    return render_template('home.html')

@app.route('/welcome')
def welcome():
    resp = google.get("/oauth2/v2/userinfo")
    assert resp.ok, resp.text
    email = resp.json()['email']
    return render_template('welcome.html', email=email)

@app.route('/login/google')
def login():
    if not google.authorized:
        return render_template(url_for('google.login'))
    resp = google.get("/oauth2/v2/userinfo")
    assert resp.ok, resp.text
    email = resp.json()['email']
    return render_template('welcome.html', email=email)

if __name__ == "__main__":
    app.run(debug=True)


from ultralytics import YOLO

# Load a model
model = YOLO("yolov8n.yaml")  # build a new model from scratch

#%%
# Use the model
model.train(data=r"C:\Users\kamra\DataspellProjects\yolov8_test\datasets\typhoon\data.yaml", epochs=100)  # train the model
metrics = model.val()  # evaluate model performance on the validation set
success = model.export(format="onnx")  # export the model to ONNX format


import logging
from logging.handlers import SysLogHandler
logger = logging.getLogger("classificationbanner")
handler = SysLogHandler(facility=SysLogHandler.LOG_DAEMON, address='/dev/log')
logger.addHandler(handler)

formatter = logging.Formatter('classification-banner[%(process)d] (%(module)s.%(funcName)s) %(levelname)s: %(message)s')
handler.setFormatter(formatter)

logger.setLevel(logging.DEBUG)

import os
import platform

import classificationbanner.utils.config  as utils_config
import classificationbanner.utils.display as utils_display

# GTK and GDK
import gi
gi.require_version("Gtk", "3.0")
gi.require_version("Gdk", "3.0")
from gi.repository import Gtk, Gdk

def get_user():
  """Helper to get logged in username"""
  try:
      user = os.getlogin()
  except:
      user = 'UnknownUser'
  return user

def get_hostname():
  """Helper to get hostname"""
  return platform.node()

class ClassificationBanner:
  def __init__(self, config=None, classification=None, location="top", banner_height=25):
    """Set up and display the banner's main window """

    # Check we have some sort of configuration
    if config is None:
      # Try to load it from the file system
      try:
        config = utils_config.open_config()
      except:
        exit(1)

    # Check that the classification is set
    if classification is None:
      # Try to load it from the configuration file
      try:
        classification = utils_config.get_system_classification(config)
      except:
        exit(1)

    # Get and save the workable area of the manager supports it.
    work_area = utils_display.get_workable_area()

    # Prepare to use our stylesheet
    style_provider = Gtk.CssProvider()
    style_filename = 'style.css'
    style_path = "/etc/classification-banner/{}".format(style_filename)
    style_provider.load_from_path(style_path)
    Gtk.StyleContext.add_provider_for_screen(
      Gdk.Screen.get_default(),
      style_provider,
      Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
    )

    # Set our current classficiation style class
    style_class = utils_config.get_classification_style_name(config, classification)
    # Die if no class is configured
    if style_class is None:
      exit(1)

    # Get some screen information and save it off
    screen_size = utils_display.get_screen_size()
    self.hres = screen_size['width']
    self.vres = screen_size['height']

    # Create Main Window
    self.window = Gtk.Window(title="Classification Banner")
    self.window.set_position(Gtk.WindowPosition.CENTER)
    self.window.set_type_hint(Gdk.WindowTypeHint.DOCK)
    self.window.set_property('skip-taskbar-hint', True)
    self.window.set_property('skip-pager-hint', True)
    self.window.stick()
    self.window.set_decorated(False)
    self.window.set_keep_above(True)
    self.window.set_app_paintable(True)
    self.window.set_default_size(self.hres, 25)

    # Our main horizontal box for label containment
    hbox = Gtk.Box(spacing=10)
    hbox.get_style_context().add_class(style_class)

    # User label
    label_user = Gtk.Label(label=get_user())
    label_user.get_style_context().add_class(style_class)
    label_user.set_halign(Gtk.Align.START)

    # Classification label
    label_classification = Gtk.Label(label=utils_config.get_classification_label(config, classification))
    label_classification.get_style_context().add_class(style_class)
    label_classification.set_halign(Gtk.Align.CENTER)

    # Hostname label
    label_hostname = Gtk.Label(label=get_hostname())
    label_hostname.get_style_context().add_class(style_class)
    label_hostname.set_halign(Gtk.Align.END)

    # Pack up the horizontal box with the labels we made
    hbox.pack_start(label_user, True, True, 0)
    hbox.pack_start(label_classification, True, True, 0)
    hbox.pack_start(label_hostname, True, True, 0)

    # Add box to window
    self.window.add(hbox)

    # Show window and attach its life to Gtk
    self.window.show_all()
    self.window.connect("destroy", Gtk.main_quit)
    if location.lower() == "top":
      # Throw a hit at X11 to make room for static elements that need to cut down on workspace
      utils_display.hint_X11(
        window=self.window,
        top=(work_area['y'] + banner_height)
      )
      # Move window into place
      self.window.move(0, work_area['y'])
    elif location.lower() == "bottom":
      # Throw a hit at X11 to make room for static elements that need to cut down on workspace
      utils_display.hint_X11(
        window=self.window,
        bottom=banner_height
      )
      # Move window into place
      self.window.move(0, work_area['height']+2)

    logger.info("Classification {} banner loaded".format(location))

def main():
  if utils_display.detect_window_system() != "x11":
    logger.critical("You must be running X11 for this utility to work.")
    exit(1)

  try:
    config = utils_config.open_config()
  except:
    exit(1)

  ClassificationBanner(config=config, location="top")
  ClassificationBanner(config=config, location="bottom")

  Gtk.main()

if __name__ == "__main__":
  main()


#MCC
import math

TP=0.6
TN=0.3
FP=0.05
FN=0.05

MCC=((TP*TN)-(FN*FP))/(math.sqrt((TP+FN)*(TN+FP)*(TP+FP)*(TN+FN)))
print(round(MCC,2))


import wx
import conf.config as config
import utils.wordActivitiesUtils as nGUtils
import utils.bottomMenu as bottomMenu
from os.path import join
import matchImageCharAnswerList
import Image

class matchPairs():
    def __init__(self, parent, id, mainWin, mainPanel, currentLesson):
        self.mainWin = mainWin
        self.mainPanel = mainPanel
        self.currentLesson = currentLesson

        self.questionList, self.questionImgList, self.answerList, self.answerNepaliList = nGUtils.nextMatchImageCharQuestion(self.currentLesson)
        self.questionImgList = resizeImage(self.questionImgList, 50)

        self.displayPanel = wx.Panel(parent, -1, (0, 0), (800, 600))
        self.displayPanel.SetBackgroundColour(config.backgroundColour)

        self.matchImageCharAnswerList = matchImageCharAnswerList.matchImageCharAnswerList(self.displayPanel, self.questionList, self.questionImgList, self.answerList, self.answerNepaliList, self.currentLesson)

        nextQuestionImg = wx.Bitmap(join(config.buttonsPath,'nextQuestion.png'), wx.BITMAP_TYPE_PNG)
        self.nextQuestionButton = wx.BitmapButton(self.displayPanel, 4, nextQuestionImg, (460,400), style = wx.NO_BORDER)
        self.nextQuestionButton.SetBackgroundColour(config.backgroundColour)
        self.nextQuestionButton.Bind(wx.EVT_BUTTON, self.OnNextQuestion, id=4)

        bottomMenu.bottomMenu([self.displayPanel], parent, self.mainWin, 'threeButton', self.mainPanel)

    def OnNextQuestion(self, event=None):
        self.questionList, self.questionImgList, self.answerList, self.answerNepaliList = nGUtils.nextMatchImageCharQuestion(self.currentLesson)
        self.questionImgList = resizeImage(self.questionImgList, 50)
        self.matchImageCharAnswerList.nextQuestion(self.questionList, self.questionImgList, self.answerList, self.answerNepaliList)

def resizeImage(imageList, resizePercent):
    newImageList = []
    for i in imageList:
        temp = Image.open(i)
        temp = temp.resize(((resizePercent*temp.size[0])/100,(resizePercent*temp.size[1])/100), Image.ANTIALIAS)
        returnNumberImg = wx.EmptyImage(temp.size[0], temp.size[1])
        returnNumberImg.SetData(temp.convert('RGB').tostring())
        returnNumberImg.SetAlphaData(temp.convert("RGBA").tostring()[3::4])
        newImageList.append(returnNumberImg)
    return newImageList


from itertools import *
from collections import *
from heapq import *
from bisect import *
from copy import *
import math
import sys
sys.setrecursionlimit(1<<20)
INF = float('inf')
n = int(input())
A = list(map(int,input().split()))
AA = []
for i,a in enumerate(A):
    AA.append((a,i))
AA.sort()
B = []
BB = list(map(int,input().split()))
for a,i in AA:
    B.append(BB[i])
dp = [[0]*(max(A)+1) for _ in range(n+1)]
mod = 998244353
dp[0][0]=1
for i in range(1,n+1):
    b = B[i-1]
    for j in range(max(A)+1):
        dp[i][j] += dp[i-1][j]
        dp[i][j]%=mod
        if j+b<=max(A):
            # print(j,b)
            dp[i][j+b] +=dp[i-1][j]
            dp[i][j+b]%=mod

ans = 0
mx = -1000000
# print(dp)
for i in range(n):
    a = AA[i][0]
    p = a-B[i]
    if p>=0:
        ans +=sum(dp[i][:p+1])
        ans %=mod
print(ans)


from graphics import *
from time import *
from player import *

windowX = int(1000)
windowY = int(1000)
used_letters = []
alphabet = {}
scoring = {}
drawing_locations = {}

class HiddenWord:
    def __init__(self):
        self.hidden_word = ""

    def get_hidden_word(self):
        return self.hidden_word

    def set_hidden_word(self, hidden_word):
        self.hidden_word = hidden_word

def main():
    mainWindow = createWindow()
    closeWindow(mainWindow)

def rebuildDisplay(secret_word): # Function to rebuild the hidden word to display the correct _ with correct characters
    new_word = ""
    for word in secret_word:
        if word != "_":
            new_word += word + " "
        else:
            new_word += "_ "
    return new_word.strip()

def wordTiles(window, current_word, state, player_input, hidden_word): # Function for getting the word to show up a individual _ representing each character
    temp_word = ""
    if state == "new state":
        for i in range(len(current_word) - 1):
            temp_word += "_ "
            hidden_word.set_hidden_word(temp_word)
    else:
        if len(player_input) == 1: #Done Tested
            for i in range(len(current_word) - 1):
                if player_input.lower() == current_word[i].lower():
                    update_word = hidden_word.get_hidden_word().split()
                    update_word[i] = player_input.lower()
                    temp_word = rebuildDisplay(update_word)
                    hidden_word.set_hidden_word(temp_word)
        else:
            if player_input.lower().strip() == current_word.lower().strip():
                temp_word = current_word
                hidden_word.set_hidden_word(temp_word)
            else:
                print("Enter single characters or whole words inside wordtiles")

    return hidden_word.get_hidden_word().strip()

def displayWordTiles(window, hidden_word): #Function for displaying wordTile
    draw_word = Text(Point(windowX/2 - 50, windowY/2 + 5), hidden_word)
    try:
        draw_word.undraw()
        draw_word.draw(window)
    except:
        draw_word.draw(window)
    return draw_word

def checkInput(current_word, player_input): #Function for check if the character or word entered by the play is correct or not
    check_result = False

    if len(player_input) == 1:
        if player_input.strip() in current_word:
            check_result = True
    else:
        if player_input.lower().strip() == current_word.lower().strip():
            check_result = True
        else:
            #TODO add function to split multiple character entry and check if each letter is in the word.
            print("Enter single characters or whole words")

    return check_result

def usedLetters(window, player_input): #Function to check if letter has already been used
    used_before = False
    letters_used = ""
    if len(player_input) == 1:
        if player_input not in used_letters:
            used_letters.append(player_input)
            this_letter = alphabet[player_input.upper()]
            this_letter.undraw()
        else:
            used_before = True

    return [used_before, letters_used]

def gameWin(current_word, hidden_word): #Function to check if word has been completed
    winner = False
    current = ""
    if current_word.lower().strip() == hidden_word.lower().strip():
        winner = True
    else:
        for i in range(len(current_word)):
            if current_word[i] != " ":
                current += current_word[i]

        if current.lower().strip() == hidden_word.lower().strip():
            winner = True

    return winner

def fixCurrentWord(current_word): #Function to get the format for the current word to match what the hidden format will look like
    word = ""
    for current_letter in current_word:
        word += current_letter + " "
    return word

def undrawInputFields():
    drawing_locations["InputBox"].undraw()
    drawing_locations["InputLabel"].undraw()
    drawing_locations["SubmitButton"].undraw()
    drawing_locations["SubmitLabel"].undraw()

def gameloop(background, window): # Function for main game loop
    hidden_word = HiddenWord()
    player = Player()
    createPlayerStats(window, player, "")
    game_words = getWords("Hangman.txt") # Returns an array of words
    current_tries = 0
    word_index = 0
    stage_names = ["Stage2", "Stage3", "Stage4", "Stage5", "Stage6", "Stage7"]

    while len(game_words) > word_index:
        win = False
        current_word = game_words[word_index]
        current_hidden = wordTiles(window, current_word, "new state", "", hidden_word)
        fixed_word = fixCurrentWord(current_word)
        draw_word = displayWordTiles(window, current_hidden)
        #entry_box = playerInputBox(window, len(current_word))
        playerInputBox(window, len(current_word))

        while current_tries <= 5 and win == False:
            win = gameWin(fixed_word, hidden_word.get_hidden_word())
            if win == True:
                print("Game Won Next Word.")
                player.update_correct_word()
                draw_word.undraw()
                undrawInputFields()
                used_letters.clear()
                current_tries = 0
                player.set_guess_counter(0)
                createPlayerStats(window, player, "")
                backgrounds("new game", window, background)
                createAlphabet(window)
                break
            elif win == False and current_tries >= 5:
                print("Game lose")
                player.update_incorrect_word()
                draw_word.undraw()
                undrawInputFields()
                used_letters.clear()
                current_tries = 0
                player.set_guess_counter(0)
                createPlayerStats(window, player, "")
                backgrounds("new game", window, background)
                createAlphabet(window)
                break
            mouse = window.getMouse() # wait for mouse click so player can enter answer
            xcoord = mouse.getX()
            ycoord = mouse.getY()
            if ((625 <= xcoord <= 684) and (540 <= ycoord <= 559)):
                #player_input = entry_box.getText()
                player_input = drawing_locations["InputBox"].getText()
                used_result, letters_used = usedLetters(window, player_input)# check if letter in entry has already been used
                if used_result == True: # start the loop over if true since the letter entered has already been used
                    drawing_locations["InputBox"].setText("")
                    continue
                check_result = checkInput(current_word, player_input)
                if check_result == True:
                    drawing_locations["InputBox"].setText("")
                    current_hidden = wordTiles(window, current_word, "", player_input, hidden_word)
                    draw_word.undraw()
                    player.update_guess_counter()
                    createPlayerStats(window, player, "counteronly")
                    draw_word = displayWordTiles(window, current_hidden)
                    sleep(.5)
                else:
                    drawing_locations["InputBox"].setText("")
                    backgrounds(stage_names[current_tries], window, background)
                    player.update_guess_counter()
                    createPlayerStats(window, player, "counteronly")
                    current_tries += 1
                    sleep(.5)
        word_index += 1

def createWindow(): #Create main window
    window = GraphWin("Game Window", windowX, windowY)
    window.setBackground("yellow")
    background = backgrounds("default", window, "")

    if window.getMouse():
        background = backgrounds("new game", window, background)
        gameloop(background, window)

    return window

def backgrounds(stage, window, old_background): #Funtion to set all stage background images
    background = ""

    if stage == 'default':
        background = Image(Point(windowX/2, windowY/2), "Stage0.gif")
        background.draw(window)
    elif stage == 'new game':
        old_background.undraw()
        background = Image(Point(windowX/2, windowY/2 - 300), "Stage1.gif")
        background.draw(window)
        createAlphabet(window)
    else:
        old_background.undraw()
        background = Image(Point(windowX/2, windowY/2 - 300), (stage + ".gif"))
        background.draw(window)

    return background

def closeWindow(window): #Function to close window on final click
    window.getMouse()
    window.close()

def playerInputBox(window, word_length): #Function for creating input box for player
    input_label = Text(Point(windowX/2 - 50, windowY/2 + 50), "Enter letter or word: ")
    input_label.draw(window)
    input_box = Entry(Point(windowX/2 + 75, windowY/2 + 50), word_length)
    input_box.draw(window)
    submit_button = Rectangle(Point(625,540), Point(684, 559))
    submit_button.draw(window)
    submit_label = Text(Point(655, 550), "Submit")
    submit_label.draw(window)
    drawing_locations.update({"InputLabel" : input_label, "InputBox" : input_box, "SubmitButton" : submit_button, "SubmitLabel" : submit_label})

    #return input_box

def createPlayerStats(window, this_player, state):
    if len(scoring) > 0 and state == "counteronly":
        this_guessLabel = scoring["guesslabel"]
        this_guessLabel.undraw()
        this_guessCounter = scoring["guesscounter"]
        this_guessCounter.undraw()
    elif len(scoring) > 0 and state != "counteronly" :
        this_correct = scoring["correct"]
        this_correct.undraw()
        this_incorrect = scoring["incorrect"]
        this_incorrect.undraw()
        this_correctLabel = scoring["correctlabel"]
        this_correctLabel.undraw()
        this_incorrectLabel = scoring["incorrectlabel"]
        this_incorrectLabel.undraw()
        this_guessLabel = scoring["guesslabel"]
        this_guessLabel.undraw()
        this_guessCounter = scoring["guesscounter"]
        this_guessCounter.undraw()

    if state == "counteronly":
        guess_counter_label = Text(Point((windowX/2 - 400), windowY/2 - 300), "Guess Counter:")
        guess_counter_label.draw(window)
        guess_counter = Text(Point((windowX/2 - 325), windowY/2 - 300), this_player.get_guess_counter())
        guess_counter.draw(window)
        scoring.update({"guesslabel" : guess_counter_label, "guesscounter" : guess_counter })
    else:
        correct_label = Text(Point((windowX/2 - 400), windowY/2 - 400), "Words Correct:")
        correct_label.draw(window)
        player_correct = Text(Point((windowX/2 - 325), windowY/2 - 400), this_player.get_words_correct())
        player_correct.draw(window)
        incorrect_label = Text(Point((windowX/2 - 400), windowY/2 - 350), "Words Incorrect:")
        incorrect_label.draw(window)
        player_incorrect = Text(Point((windowX/2 - 325), windowY/2 - 350), this_player.get_words_incorrect())
        player_incorrect.draw(window)
        guess_counter_label = Text(Point((windowX/2 - 400), windowY/2 - 300), "Guess Counter:")
        guess_counter_label.draw(window)
        guess_counter = Text(Point((windowX/2 - 325), windowY/2 - 300), this_player.get_guess_counter())
        guess_counter.draw(window)
        scoring.update({"correctlabel" : correct_label, "correct" : player_correct, "incorrectlabel" : incorrect_label , "incorrect" : player_incorrect, "guesslabel" : guess_counter_label, "guesscounter" : guess_counter })

def createAlphabet(window): #Function to set the starting alphabet
    alpha = ['A','B','C','D','E','F','G','H','I','J','K',
            'L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z']
    reset(window, alpha)
    for i in range (len(alpha)):
        singleLetter = Text(Point((windowX/2 - 200) + (i*15), windowY/2 + 100), alpha[i])
        singleLetter.draw(window)
        alphabet.update({alpha[i] : singleLetter})

def reset(window, letters): #Function resets the letters back to origianal unused state
    try:
        for letter in letters:
            this_letter = alphabet[letter.upper()]
            this_letter.undraw()
    except:
        print("nothing to undraw.")

def getWords(filedata): #Function to get the words from a file that will be used in the game
    words = []
    List_of_Words = open (filedata, 'r')
    allWords = List_of_Words.readlines()
    List_of_Words.close()

    # make sure each word is lowercase
    for i in range (len (allWords)):
        choosenWord = allWords[i].lower()
        words.append(choosenWord)

    return words
main()

""" TODO
Backlog
X 1. undraw words correct and incorrect when updating score. Code is currently just redrawing a new image over top of the others.
X 2. undraw Enter letter or word text when moving to new word. Code is currently just redrawing the text again when moving to a new word after refreshing all the images
X 3. add a guesses counter to show player how many tries it took to guess the current word.
  4. add a hint box so the player can click and get a hint for the current word. """


import numpy as np
import copy
from dataInfo import dataInfo
from createNode import createNode
import xml.etree.cElementTree as ET
from readData import readData
import sys

def getDistOfPnts(subMat):
    dict = {}
    for key in subMat[:,-1]:
        if key in dict:
            dict[key] += 1
        else:
            dict[key] = 1
    return dict

def calGain(dict1, dict2, mdlName):
    sumFor1 = 0.0
    sumFor2 = 0.0
    n1 = 0.0
    n2 = 0.0
    for key in dict1.keys():
        n1 += dict1[key]
        n2 += dict2[key]
        if mdlName == 'gini':
            sumFor1 += (dict1[key]) ** 2
            sumFor2 += (dict2[key]) ** 2
        elif mdlName == 'information gain':
            if dict1[key] != 0.0: sumFor1 += (dict1[key]) * np.log2(dict1[key])
            if dict2[key] != 0.0: sumFor2 += (dict2[key]) * np.log2(dict2[key])
    if mdlName == 'gini':
        if n1 != 0.0:sumFor1 = 1 - sumFor1 / (n1 ** 2)
        if n2 != 0.0: sumFor2 = 1 - sumFor2 / (n2 ** 2)
    elif mdlName == 'information gain':
        if n1 != 0.0:sumFor1 = np.log2(n1) - sumFor1 / n1
        if n2 != 0.0: sumFor2 = np.log2(n2) - sumFor2 / n2
    try:
        r = n1/(n1+n2)* sumFor1 + n2 / (n1 + n2)* sumFor2
    except Exception as error:
        print('Caught this error: ' + repr(error))
    return n1, n2, r

def findTresh(firstPnt, secondPnt, prntGain, subMat, n1, n2, mdlName):
    chldGain = prntGain
    bestSndPnt = {}
    bestFrstPnt = {}
    bestInd = 0

    for c in subMat[:, -1]:
        firstPnt[c] +=1
        secondPnt[c] -= 1
        n1 += 1
        n2 -= 1
        _, _, gain = calGain(firstPnt, secondPnt, mdlName)
        if gain < chldGain :
            chldGain = gain
            bestFrstPnt = copy.copy(firstPnt)
            bestSndPnt = copy.copy(secondPnt)
            bestInd = int(n1)
        #gain = np.append(gain, [calGain(firstPnt, secondPnt, n1, n2)], axis=0)

    splitGn = prntGain - chldGain
    return splitGn, bestFrstPnt, bestSndPnt, bestInd

def find_best_split(inst, mdlName):
    secondPnt = inst.clsDist
    firstPnt = {}
    for key in secondPnt.keys():
        firstPnt[key] = 0
    [n1, n2, prntGain] = calGain(firstPnt, secondPnt, mdlName)
    maxSpltGn = -1
    maxGnInd = -1

    for i in range(0,len(inst.data[0,:])-1):
        numbAttr = inst.data[:,i].astype(float)
        #if np.isnan(inst.indices[0,i]):
        ind = (numbAttr).argsort()
        inst.indices[:,i] = ind
        #else:
        #    ind = range(0,inst.data[:,0].size)
        subMat = np.array([numbAttr[ind], inst.data[ind, - 1]]).transpose()
        #[firstPnt, secondPnt, n1, n2] = getDistOfPnts(subMat)
        [splitGn, _, _, _] = findTresh(copy.copy(firstPnt), copy.copy(secondPnt), prntGain, subMat, n1, n2, mdlName)
        if splitGn > maxSpltGn:
            maxSpltGn = splitGn
            maxGnInd = i
    if maxSpltGn == 0:
        print("No progress error")
    numbAttr = inst.data[:, maxGnInd].astype(float).transpose()
    ind = inst.indices[:, maxGnInd].astype(int)
    subMat = np.array([numbAttr[ind], inst.data[ind, - 1]]).transpose()
    [splitGn, bestFrstPnt, bestSndPnt, bestInd] = findTresh(copy.copy(firstPnt), copy.copy(secondPnt), prntGain, subMat, n1, n2, mdlName)
    tresh = (numbAttr[ind[bestInd-1]]+ numbAttr[ind[bestInd]]) / 2.0
    sub1 = inst.data[ind[0:bestInd], :]
    sub2 = inst.data[ind[bestInd:], :]
    #indicesMat = (inst.indices[:,:-1])
    #indicesMat = indicesMat.flatten('F')
    #indicesMat = np.reshape(indicesMat,)
    #maskMat = inst.indices[:,maxGnInd] < bestInd
    #vecInd1 = indicesMat[maskMat]
    #vecInd2 = indicesMat[np.invert(maskMat)]
    #indices1 = np.reshape(vecInd1, (bestInd, 3), order='F')
    #indices2 = np.reshape(vecInd2, (10 - bestInd, 3), order='F')
    #indices1 = inst.indices[maskMat,:]
    #indices2 = inst.indices[np.invert(maskMat),:]
    #print(inst.indices, '\n', indices1, '\n', indices2)
    node1 = dataInfo(sub1, bestFrstPnt, np.zeros(shape=(sub1).shape))
    node2 = dataInfo(sub2, bestSndPnt, np.zeros(shape=(sub2).shape))
    return node1, node2, tresh, maxGnInd

#def find_best_split(inst, attr):
#    dataSize = inst.shape
#    numOfClm = dataSize[1]
#    numOfRow = dataSize[0]
#    [clsDist1, clsDist2, splitGn, sub1, sub2, thresh] = calImpurity(inst, attr)
#    while (splitGn < 0 and attr[0] < numOfClm-1):
#        attr[0] += 1
#        attr[1] = 0
#        [clsDist1, clsDist2, splitGn, sub1, sub2, thresh] = calImpurity(inst, attr)
#    if splitGn <0: print("ERROR!")
#    return clsDist1, clsDist2, thresh, sub1, sub2,

def stopping_cond(inst, mdlName, epsl):
    try:
        _, _, gain = calGain(inst.clsDist, inst.clsDist, mdlName)
    except Exception as error:
        _, _, gain = calGain(inst.clsDist, inst.clsDist, mdlName)
    try:
        a1 = (inst.data[:,0].size) * inst.data[0,:-1]
    except Exception as error:
        print('Caught this error: ' + repr(error))
    a2 = np.sum(inst.data[:, :-1], axis=0)
    if gain < epsl or  np.array_equal(a1, a2) :
        return True
    return False

def Classify(clsDist):
    mainClass = 0
    mainKey = 0
    for key in clsDist:
        if clsDist[key] > mainClass: mainKey = key
    return mainKey

def TreeGrowth (inst, level, mdlName, root = None):
    level += 1
    if root == None:
        inst.indices = np.zeros(shape=(inst.data).shape)
        #inst.sorted = np.zeros(shape=(inst.data[0,:]).shape)
        inst.indices[:] = np.nan
        inst.clsDist = getDistOfPnts(inst.data)
        root = ET.Element("Node", name="root")
    if stopping_cond(inst, mdlName, 0.001) == True:
        #leaf = createNode(clsDist)
        #leaf.setLabel()
        label = Classify(inst.clsDist)
        data = ET.SubElement(root, "data")
        ET.SubElement(data, "test_cond").text = ""
        ET.SubElement(data, "label").text = repr(label)
        ET.SubElement(data, "attrNum").text = ""
        #print(inst.data,'\n\n')
        return 0#leaf
    else:
        #key = iter(clsDist)
        #root = createNode(level, clsDist[next(key)], clsDist[next(key)], inst.shape)
        [node1, node2, v, maxGnInd]= find_best_split(inst, mdlName)
        data = ET.SubElement(root, "data")
        ET.SubElement(data, "test_cond").text = repr(v)
        ET.SubElement(data, "label").text = ""
        ET.SubElement(data, "attrNum").text = repr(maxGnInd)
        lftChld = ET.SubElement(root, "Node", name="leftChild")
        child = TreeGrowth(node1, level, mdlName, lftChld)
        #root.setLftChld(child.getID)
        #root.addTestCond(v)
        rghtChld = ET.SubElement(root, "Node", name="rightChild")
        child = TreeGrowth(node2, level, mdlName, rghtChld)
        #root.setRghtChld(child.getID)
        #for v in V:
        #    subInst = distr(inst, v) #(e I root.test..cond(e) = v and e EE}.
        #    child= TreeGrowth(subInst, attr)
        #    root.addEdge(v, child)
    return root

#main body of the program for loading data and
# running a recursive tree function to learn from data
args = iter(sys.argv)
next(args)
mdlName = ""
inputFileTr = ""
inputClassesTr = ""
inputFileTs = ""
inputClassesTs = ""
for item in args:
    if item == "-m":
        mdlName = next(args)
    elif item == "-itr1":
        inputFileTr = next(args)
    elif item == "-itr2":
        inputClassesTr = next(args)
    elif item == "-its1":
        inputFileTs = next(args)
    elif item == "-its2":
        inputClassesTs = next(args)

if inputFileTr.lower() == "" or inputClassesTr == "" or (mdlName.lower() != "gini"  and mdlName.lower() != "information gain"):#or inputFileTs.lower() == "" or inputClassesTs.lower() == "" or
    print("You have NOT entered one of the required inputs!")
    sys.exit()

#mdlName = "information gain"
#inputFileTr = "X_iris.txt"
#inputClassesTr = "y_iris.txt"
#inputFileTs = "X_test.txt"
#inputClassesTs = "y_test.txt"

print("\nReading 1 set of data ...")
clases = readData(inputClassesTr)
data1 = readData(inputFileTr)
data1 = np.append(data1, clases, axis=1)

if inputClassesTs != "":
    print("\nReading 2 set of data ...")
    clases = readData(inputClassesTs)
    data2 = readData(inputFileTs)
    data2 = np.append(data2, clases, axis=1)

data = np.append(data1, data2, axis=0) if (inputClassesTs != "") else data1

#sh = instances.shape
#data = np.empty((sh[0], sh[1]+1), float)
#print(data.shape)
#data[:,:-1] = instances
#data[:,-1] = clases
#data = np.array([[1, 1, 125, "No"],
#                [0, 2, 100, "Yes"],
#                [0, 1, 70, "No"],
#                [1, 2, 120, "No"],
#                [0, 3, 95, "Yes"],
#                [0, 2, 60, "No"],
#                [1, 3, 220, "No"],
#                [0, 1, 85, "Yes"],
#                [0, 2, 75, "No"],
#                [0, 1, 90, "Yes"]])

print("\nTraining a tree model ...")
arraySize = int(data[:,0].size )
randIndx = np.random.choice([True, False], arraySize)#[bool(random.getrandbits(1)) for i in range(arraySize)]
invIndx = [not i for i in randIndx]
np.save( 'randData' , randIndx)
np.save( 'invtRandData' , invIndx)
inst = dataInfo(data[randIndx, :])
root = TreeGrowth (inst, 0, mdlName.lower())

tree = ET.ElementTree(root)
tree.write("trained_Tree.xml")
print("\nThe tree model has been trained,\nYou can look at it in a file named \"trained_Tree.xml\"\nwhich is created inside your project folder")
#saveTree(root)


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('profiles', '0016_delete_defaultavatar'),
    ]

    operations = [
        migrations.AddField(
            model_name='profilesettings',
            name='is_provider',
            field=models.BooleanField(help_text='provider functionality', default=True, verbose_name='I am provider'),
        ),
    ]


from decimal import Decimal
from django.shortcuts import render, HttpResponseRedirect
from .models import Cart, CartItem
from django.urls import reverse
from products.models import Product, Variation
# Create your views here.
def view(request):
    try:
        the_id = request.session['cart_id']
        cart = Cart.objects.get(id=the_id)
    except:
        the_id = None
    if the_id:
        context = {"cart": cart}
        new_total = 0.00
        for item in cart.cartitem_set.all():
            line_total =  float(item.product.price) * item.quantity
            new_total += line_total
        request.session['items_total'] = cart.cartitem_set.count()
        two_dec_digits = Decimal(10)  ** -2
        cart.total = Decimal(new_total).quantize(two_dec_digits)
        if cart.total == 0:
            message = "Your Cart is EMPTY"
            context = {"empty": True, "message": message}
        cart.save()
    else:
        message = "Your Cart is EMPTY"
        context = {"empty": True, "message": message}
    template = 'cart/view.html'
    return render(request, template, context)

def remove_from_cart(request, id):
    try:
        the_id = request.session['cart_id']
        cart = Cart.objects.get(id=the_id)
    except:
        return HttpResponseRedirect(reverse("cart"))
    cartitem = CartItem.objects.get(id=id)
    cartitem.delete()
    # cartitem.cart = None
    # cartitem.save()
    return HttpResponseRedirect(reverse("cart"))

def add_to_cart(request, slug):
    try:
        qty = request.GET.get('qty')
        update_qty = True
    except:
        qty = None
        update_qty = False
    try:
        the_id = request.session['cart_id']
    except:
        new_cart = Cart()
        new_cart.save()
        request.session['cart_id'] = new_cart.id
        the_id = new_cart.id
    cart = Cart.objects.get(id=the_id)
    try:
        product = Product.objects.get(slug=slug)
    except Product.DoesNotExist:
        pass
    except:
        pass

    product_var = []
    if request.method == "POST":
        qty = request.POST['qty']
        for item in request.POST:
            key = item
            val = request.POST[key]
            try:
                v = Variation.objects.get(product = product, category__iexact = key, title__iexact = val)
                product_var.append(v)
            except:
                pass

        cart_item = CartItem.objects.create(cart=cart,product=product)

        if len(product_var) > 0:
            cart_item.variations.add(*product_var)
        cart_item.quantity = qty
        cart_item.save()
        return HttpResponseRedirect(reverse("cart"))
    return HttpResponseRedirect(reverse("cart"))


_exec_relative_('../sparsesample_RGB_crop224_8frame_largejit_plateau_10scrop.py')

input_frame_length = 24

def batch_size():
    '''batch_size can be either integer or function returning integer.
    '''
    devices=list(range(torch.cuda.device_count()))
    vram = min([torch.cuda.get_device_properties(device).total_memory for device in devices])
    if vram > 20e+9:
        return 8
    elif vram > 10e+9:
        return 4
    return 2


# p2pclient.py
# ------------
# The P2P client component
# Handle user interaction, controls the server
# Communicate with server via UNIX DOMAIN SOCKETS

import os
import socket
import sys
import shutil

from libprotocol import libp2puds
from libprotocol.libp2puds import UdsResponsePacket

# CONSTANTS
CLIENT_UDS_PATH  = "./p2pvar/uds_socket"
CLIENT_ROOT_PATH = "./p2pvar/"
MAX_PACKET_SIZE = 1024

class P2PClient(object):

    def _send_uds_request(self, packet):
        sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
        sock.connect(CLIENT_UDS_PATH)
        sock.sendall(packet.encode_bytes())

        data_string = ""
        while True:
            try:
                data = sock.recv(MAX_PACKET_SIZE)
                data_string = data_string + data.decode("utf-8")

                # print("-------", data_string)
                res_pkt = UdsResponsePacket.parse(data_string)
                sock.close()
                return res_pkt
            except ValueError as err:
                if int(str(err)) == libp2puds.INCOMPLETE_PACKET_ERROR:
                    continue
                if int(str(err)) == libp2puds.MALFORMED_PACKET_ERROR:
                    raise err

    def setup(self):
        print("P2P CLIENT INITIALISING...")
        init_peer_table_req = libp2puds.construct_init_req()

        try:
            self._send_uds_request(init_peer_table_req)
        except ValueError as err:
            if int(str(err)) == libp2puds.MALFORMED_PACKET_ERROR:
                exit(libp2puds.MALFORMED_PACKET_ERROR)

    def _render_user_menu(self):
        print("Group 14 P2P Client")
        print("-------------------")
        print("1. List available files.")
        print("2. Share a file.")
        print("3. Download a file.")
        print("4. Search for a file.")
        print("5. Quit")

    def _process_user_option(self, user_option):
        if user_option == "1":
            list_req = libp2puds.construct_list_files_req()
            res_pkt = self._send_uds_request(list_req)
            print(list(set(res_pkt.data)))

        elif user_option == "2":
            filepath = input('Enter filepath: ')
            shutil.copy(filepath, CLIENT_ROOT_PATH + os.path.basename(filepath))
            upload_req = libp2puds.construct_upload_file_req(os.path.basename(filepath))
            res_pkt =  self._send_uds_request(upload_req)

            if res_pkt.code == libp2puds.OK_RES_CODE:
                print("File uploaded")
            else:
                print("An error occurred")

        elif user_option == "3":
            filename = input('Enter filename: ')
            download_req = libp2puds.construct_download_file_req(filename)
            res_pkt =  self._send_uds_request(download_req)

            if res_pkt.code == libp2puds.OK_RES_CODE:
                file_data = res_pkt.data[0].encode()
                with open(CLIENT_ROOT_PATH + filename, "wb") as file:
                    file.write(file_data)
                print("File downloaded!")
            else:
                print("File not found")

        elif user_option == "4":
            filename = input('Enter filename: ')
            list_req = libp2puds.construct_list_files_req()
            res_pkt = self._send_uds_request(list_req)
            if(filename in res_pkt.data):
                print('%s exists' % filename)
            else:
                print('%s not found' % filename)

        elif user_option == "5":
            sys.exit()
        else:
            pass

    def run(self):
        while 1:
            self._render_user_menu()
            user_option = input('Enter option: ')
            while user_option not in ["1", "2", "3", "4", "5"]:
                user_option = input('Invalid option selected. Please try again: ')
            self._process_user_option(user_option)


import json
import multiprocessing as mp
import numpy as np
import pyflex
import torch
from scipy.spatial.transform import Rotation as R

from core.util.args import get_args
from core.util.util import quatFromAxisAngle, quatFromAxisAngle_batch

def _worker(remote, parent_remote, env_fn_wrapper, gpu_id, gui):
    parent_remote.close()
    env = env_fn_wrapper.var(gpu_id=gpu_id, gui=gui)
    while True:
        try:
            cmd, data = remote.recv()
            if cmd == 'step':
                observation, reward, done, info = env.step(data)
                if done:
                    observation = env.reset()
                remote.send((observation, reward, done, info))
            elif cmd == 'reset':
                observation = env.reset()
                remote.send(observation)
            elif cmd == 'reload':
                env.reload(data)
            elif cmd == 'render':
                remote.send(env.render(*data[0], **data[1]))
            elif cmd == 'close':
                remote.close()
                break
            elif cmd == 'get_spaces':
                remote.send((env.observation_space, env.action_space))
            elif cmd == 'env_method':
                method = getattr(env, data[0])
                remote.send(method(*data[1], **data[2]))
            elif cmd == 'get_attr':
                remote.send(getattr(env, data))
            elif cmd == 'set_attr':
                remote.send(setattr(env, data[0], data[1]))
            elif cmd == 'sample_action':
                remote.send(env.sample_action())
            else:
                raise NotImplementedError
        except EOFError:
            break

class PyFlexEnv():
    """
    This is the base class for the PyFleX based simulators.
    In the base class, the action space and the state space are assumed to be (x,y,z,theta). Theta is the gripper rotation angle
    """

    def __init__(self, name, micro_action_steps, gpu_id, gui):

        self.name = name
        self.micro_action_steps = micro_action_steps
        self.gpu_id = gpu_id
        self.particle_radius = 400
        self.dim_shape_state = 14

        self.clip_force = 0.01
        self.lift_force = 0.035
        self.init_height = 0.2

        # set up gripper
        with open(get_args().gripper_conf) as f:
            gripper = json.load(f)

        self.rest_gripper_dis = gripper['rest_gripper_dis'] + 0.016  # allow some buffer
        self.center = None
        self.halfEdge = np.array(gripper['halfEdge'])
        self.halfEdge_cap = np.array(gripper['halfEdge_cap'])
        pyflex.init(gui)

    def reset(self):

        pyflex.set_scene(0, self.positions.numpy(), self.particle_radius)
        r = R.from_quat(pyflex.get_rigidRotations())
        self.base_ori = r.as_euler('xyz', degrees=False)[1]
        self.clip_steps = 0

        center = np.array([5, 0.0, 5])
        quat = np.array([1., 0., 0., 0.])

        pyflex.add_box(self.halfEdge, center, quat)
        pyflex.add_box(self.halfEdge, center, quat)
        pyflex.add_box(self.halfEdge_cap, center, quat)
        pyflex.step()  # otherwise black screen

        return self._get_obs()

    def load_point_cloud(self):
        cloud = self.pc
        positions = torch.zeros((cloud.shape[0], 4))
        for idx, p in enumerate(cloud):
            # vertical axis z correspond to y in flex
            positions[idx] = torch.tensor([p[0], max(p[2], 0), p[1], 10000])
        return positions

    def reload(self, pc_path):

        self.pc = torch.tensor(np.loadtxt(pc_path)).float()
        self.center = self.pc.mean(0)
        self.positions = self.load_point_cloud()

    def step(self, action):

        pyflex.set_friction(0.03)  # enable rotation effect
        for i in range(int(self.micro_action_steps / 3), self.micro_action_steps):
            if i == int(self.micro_action_steps * 2 / 3):
                pyflex.set_friction(1.0)  # enable grasping

            self.shape_states = self.calc_shape_states(i, self.clip_steps, action)
            if not self.collision_check_gripper():
                # no collision and continue clipping
                self.clip_steps += 1

            pyflex.set_shape_states(self.shape_states)
            pyflex.step()

        done = self._done()
        obs = self._get_obs()
        reward, info = self._reward_func(action)

        return obs, reward, done, info

    def collision_check_gripper(self):
        # check two grippers collision, to avoid penetration
        contact_lines = pyflex.get_contacts()
        conatact_lines = torch.tensor(contact_lines).float().view(-1, 6)

        # find out horizontal contact forces
        start_pos = conatact_lines[:, [0, 2]]
        gripper_0 = torch.tensor(self.shape_states[0, [0, 2]]).repeat(conatact_lines.size(0), 1).float()
        gripper_1 = torch.tensor(self.shape_states[1, [0, 2]]).repeat(conatact_lines.size(0), 1).float()

        dis_to_g0 = torch.pow(start_pos - gripper_0, 2).sum(dim=1).sqrt()
        dis_to_g1 = torch.pow(start_pos - gripper_1, 2).sum(dim=1).sqrt()

        g0_touch_num = (dis_to_g0 < self.clip_force).int().sum()
        g1_touch_num = (dis_to_g1 < self.clip_force).int().sum()

        return g0_touch_num > 5 and g1_touch_num > 5

    def calc_shape_states_batch(self, t, clip_steps, action, device="cuda"):
        # unit test pass
        # robot tip graping point: xyh theta. h is height in flex.
        action = action.to(device).float()
        x, y, h, alpha = action[:, 0], action[:, 1], action[:, 2], action[:, 3]

        time_step = self.micro_action_steps
        half_rest_gripper_dis = self.rest_gripper_dis / 2.
        alpha = torch.atan2(torch.sin(torch.deg2rad(alpha)), torch.cos(torch.deg2rad(alpha)))  # normalize angle

        a, b = torch.cos(alpha) * half_rest_gripper_dis, torch.sin(alpha) * half_rest_gripper_dis
        x_init_0, z_init_0 = x + a, y + b
        x_init_1, z_init_1 = x - a, y - b

        progress = min(clip_steps / (time_step / 3), 1)
        e_0_curr = torch.cat(((x_init_0 - progress * a - torch.cos(alpha) * self.clip_force).view(-1, 1),
                              h.view(-1, 1),
                              (z_init_0 - progress * b - torch.sin(alpha) * self.clip_force).view(-1, 1)), dim=1)
        e_1_curr = torch.cat(((x_init_1 + progress * a + torch.cos(alpha) * self.clip_force).view(-1, 1),
                              h.view(-1, 1),
                              (z_init_1 + progress * b + torch.sin(alpha) * self.clip_force).view(-1, 1)), dim=1)
        e_0_last = torch.cat(((x_init_0 - progress * a).view(-1, 1),
                              h.view(-1, 1),
                              (z_init_0 - progress * b).view(-1, 1)), dim=1)
        e_1_last = torch.cat(((x_init_1 + progress * a).view(-1, 1),
                              h.view(-1, 1),
                              (z_init_1 + progress * b).view(-1, 1)), dim=1)
        if t > time_step * 2 / 3:
            t = t - time_step * 2 / 3
            progress = t / (time_step / 3)
            e_0_curr[:, 1] = progress * self.init_height + h + self.lift_force
            e_1_curr[:, 1] = progress * self.init_height + h + self.lift_force

            e_0_last[:, 1] = progress * self.init_height + h
            e_1_last[:, 1] = progress * self.init_height + h

        quat = quatFromAxisAngle_batch(torch.arctan(torch.cos(alpha) / torch.sin(alpha)))

        e_2_curr = torch.cat((((e_0_last[:, 0] + e_1_last[:, 0]) / 2).view(-1, 1),
                              (e_0_last[:, 1] + self.halfEdge[1] + self.halfEdge_cap[1] - 0.01).view(-1, 1),
                              ((e_0_last[:, 2] + e_1_last[:, 2]) / 2).view(-1, 1)), dim=1)
        e_2_last = torch.cat((((e_0_last[:, 0] + e_1_last[:, 0]) / 2).view(-1, 1),
                              (e_0_last[:, 1] + self.halfEdge[1] + self.halfEdge_cap[1]).view(-1, 1),
                              ((e_0_last[:, 2] + e_1_last[:, 2]) / 2).view(-1, 1)), dim=1)

        return e_0_curr, e_0_last, e_1_curr, e_1_last, e_2_curr, e_2_last, quat

    def calc_shape_states(self, t, clip_steps, action):
        x, y, h, alpha = action

        time_step = self.micro_action_steps
        half_rest_gripper_dis = self.rest_gripper_dis / 2.
        alpha = np.arctan2(np.sin(np.radians(alpha)), np.cos(np.radians(alpha)))  # normalize angle

        a, b = np.cos(alpha) * half_rest_gripper_dis, np.sin(alpha) * half_rest_gripper_dis
        x_init_0, z_init_0 = x + a, y + b
        x_init_1, z_init_1 = x - a, y - b

        progress = min(clip_steps / (time_step / 3), 1)
        e_0_curr = np.array([x_init_0 - progress * a - np.cos(alpha) * self.clip_force, h,
                             z_init_0 - progress * b - np.sin(alpha) * self.clip_force])
        e_1_curr = np.array([x_init_1 + progress * a + np.cos(alpha) * self.clip_force, h,
                             z_init_1 + progress * b + np.sin(alpha) * self.clip_force])
        e_0_last = np.array(
            [x_init_0 - progress * a, h,
             z_init_0 - progress * b])
        e_1_last = np.array(
            [x_init_1 + progress * a, h,
             z_init_1 + progress * b])
        if t > time_step * 2 / 3:
            t = t - time_step * 2 / 3
            e_0_curr[1] = t / (time_step / 3) * self.init_height + h + self.lift_force
            e_1_curr[1] = t / (time_step / 3) * self.init_height + h + self.lift_force

            e_0_last[1] = t / (time_step / 3) * self.init_height + h - 0.02
            e_1_last[1] = t / (time_step / 3) * self.init_height + h - 0.02

        states = np.zeros((3, self.dim_shape_state))

        quat = quatFromAxisAngle(np.array([0., 1., 0.]), np.arctan(np.cos(alpha) / np.sin(alpha)))
        states[0, :3] = e_0_curr
        states[0, 3:6] = e_0_last
        states[0, 6:10] = quat
        states[0, 10:14] = quat

        states[1, :3] = e_1_curr
        states[1, 3:6] = e_1_last
        states[1, 6:10] = quat
        states[1, 10:14] = quat

        states[2, :3] = np.array(

            [(e_0_last[0] + e_1_last[0]) / 2, e_0_last[1] + self.halfEdge[1] + self.halfEdge_cap[1] - 0.01,
             (e_0_last[2] + e_1_last[2]) / 2])
        states[2, 3:6] = np.array(
            [(e_0_last[0] + e_1_last[0]) / 2, e_0_last[1] + self.halfEdge[1] + self.halfEdge_cap[1],
             (e_0_last[2] + e_1_last[2]) / 2])

        states[2, 6:10] = quat
        states[2, 10:14] = quat

        return states

    def _reward_func(self, action):
        raise NotImplementedError

    def _move_particle(self, act):
        raise NotImplementedError

    def _done(self):
        raise NotImplementedError

    def _get_obs(self):
        return None

class GraspEnv(PyFlexEnv):
    fail_reward = -1000000

    def __init__(self, name="Nvidia FleX Grasp Simulation", micro_action_steps=60, gpu_id=0, gui=0):
        super().__init__(name, micro_action_steps, gpu_id, gui)

    def _reward_func(self, action):
        new_pos = pyflex.get_positions()
        new_pos = new_pos.reshape(self.positions.shape)
        new_pos = torch.tensor(new_pos).float()[:, :3]
        height_old = self.positions[:, 1].max().item()
        height_new = new_pos[:, 1].max().item()

        if height_new - height_old < 0.12:
            return self.fail_reward, ""

        # rotation, evaluate the robustness
        move_vec = new_pos - self.positions[:, :3]
        move_vec_x, move_vec_z = move_vec[:, 0], move_vec[:, 2]
        error = move_vec_x.square().sum() + move_vec_z.square().sum()

        return error.item() * -1, ""

    def _done(self):
        return True

    def _get_obs(self):
        return None

    def _get_action_space(self):
        return self.action_space

    def _get_observation_space(self):
        return self.observation_space

    def get_spaces(self):
        return self._get_observation_space(), self._get_action_space()

    def sample_action(self):
        return self.action_space.sample()

class CloudpickleWrapper(object):
    def __init__(self, var):
        """
        Uses cloudpickle to serialize contents (otherwise multiprocessing tries to use pickle)
        :param var: (Any) the variable you wish to wrap for pickling with cloudpickle
        """
        self.var = var

    def __getstate__(self):
        import cloudpickle
        return cloudpickle.dumps(self.var)

    def __setstate__(self, obs):
        import cloudpickle
        self.var = cloudpickle.loads(obs)

class VectorEnv():
    """
    This implements the vectorized environment for the pyflex environments. The implementation follows OpenAI
    baselines: https://github.com/openai/baselines
    """

    def __init__(self, env_fns, start_method=None, gpu_id=0, gui=0):
        self.waiting = False
        self.closed = False
        self.n_envs = len(env_fns)

        if start_method is None:
            # Fork is not a thread safe method (see issue #217)
            # but is more user friendly (does not require to wrap the code in
            # a `if __name__ == "__main__":`)
            forkserver_available = 'forkserver' in mp.get_all_start_methods()
            start_method = 'forkserver' if forkserver_available else 'spawn'

        ctx = mp.get_context(start_method)

        self.remotes, self.work_remotes = zip(
            *[ctx.Pipe() for _ in range(self.n_envs)])
        self.processes = []
        for work_remote, remote, env_fn in zip(self.work_remotes, self.remotes, env_fns):
            args = (work_remote, remote, CloudpickleWrapper(env_fn), gpu_id, gui * int(len(self.processes) < 1))
            process = ctx.Process(target=_worker, args=args, daemon=True)
            process.start()
            self.processes.append(process)
            work_remote.close()

    def step(self, actions):
        self.step_async(actions)
        return self.step_wait()

    def step_async(self, actions):
        for remote, action in zip(self.remotes, actions):
            remote.send(('step', action))
        self.waiting = True

    def step_wait(self):
        results = [remote.recv() for remote in self.remotes]
        self.waiting = False
        obs, rews, dones, infos = zip(*results)
        return np.stack(obs), np.stack(rews), np.stack(dones), infos

    def sample_actions(self):
        for remote in self.remotes:
            remote.send(('sample_action', None))
        self.waiting = True

        results = [remove.recv() for remove in self.remotes]
        self.waiting = False
        return np.stack(results)

    def reset(self):
        for remote in self.remotes:
            remote.send(('reset', None))
        obs = [remote.recv() for remote in self.remotes]
        return np.stack(obs)

    def reload(self, action):
        # reload new particles from file
        for remote in self.remotes:
            remote.send(('reload', action))

    def reloads(self, actions):
        for remote, action in zip(self.remotes, actions):
            remote.send(('reload', action))

    def close(self):
        if self.closed:
            return
        if self.waiting:
            for remote in self.remotes:
                remote.recv()
        for remote in self.remotes:
            remote.send(('close', None))
        for process in self.processes:
            process.join()
        self.closed = True


import io
import os
import textwrap

from PIL import Image, ImageDraw, ImageFont

from userge import Message, userge

@userge.on_cmd(
    "slet",
    about={
        "header": "Get a Sticker",
        "description": "Generates Sticker with provided text",
        "usage": "{tr}slet [text | reply]",
        "examples": "{tr}slet DeadSun",
    },
    allow_via_bot=False,
)
async def sticklet(message: Message):
    sticktext = message.input_or_reply_str
    if not sticktext:
        await message.edit("**Bruh** ~`I need some text to make sticklet`")
        return
    await message.delete()
    if message.reply_to_message:
        reply_to = message.reply_to_message.message_id
    else:
        reply_to = message.message_id
    # https://docs.python.org/3/library/textwrap.html#textwrap.wrap

    sticktext = find_optimal_wrap(sticktext)
    sticktext = "\n".join(sticktext)

    image = Image.new("RGBA", (512, 512), (255, 255, 255, 0))
    draw = ImageDraw.Draw(image)
    fontsize = 230
    font = ImageFont.truetype("resources/Roboto-Regular.ttf", size=fontsize)

    while True:
        current_size = draw.multiline_textsize(
            sticktext, font=font, stroke_width=6, spacing=-10
        )

        if current_size[0] <= 512 and current_size[1] <= 512 - 64:
            break

        fontsize -= 3
        font = ImageFont.truetype("resources/Roboto-Regular.ttf", size=fontsize)
    width, height = draw.multiline_textsize(
        sticktext, font=font, stroke_width=6, spacing=-10
    )
    image = Image.new("RGBA", (512, height + 64), (255, 255, 255, 0))
    draw = ImageDraw.Draw(image)
    draw.multiline_text(
        (int((512 - width) / 2), 0),
        sticktext,
        font=font,
        fill="white",
        stroke_width=6,
        stroke_fill="black",
        spacing=-10,
    )
    bbox = image.getbbox()
    image = image.crop((0, bbox[1], 512, bbox[3]))

    image_name = io.BytesIO()
    image_name.name = "sticker.webp"
    image.save(image_name, "WebP")
    image_name.seek(0)

    await userge.send_sticker(
        chat_id=message.chat.id, sticker=image_name, reply_to_message_id=reply_to
    )

    # cleanup
    try:
        os.remove(image_name)
    except Exception:
        pass

def find_optimal_wrap(text):
    chicken_wrap = int(len(text) / 18) or 20
    wrapped_text = textwrap.wrap(text, width=chicken_wrap)

    while len(wrapped_text) * 3 > chicken_wrap:
        chicken_wrap += 1
        wrapped_text = textwrap.wrap(text, width=chicken_wrap)

    return wrapped_text