import json
import pathlib
from datetime import datetime
from decimal import Decimal
from typing import List

import matplotlib.pyplot as plt
import matplotlib.transforms as transforms
import pandas as pd

from src.backtest.backtest_data_type import HedgeTrade, HedgeType, LogState
from src.exchange.ftx.ftx_data_type import FtxHedgePair
from src.indicator.base_indicator import BaseIndicator

def logs_to_summary(logs: List[LogState]) -> dict:
    if len(logs) == 0:
        return {"avg_deposit": 0, "profit": 0, "roi": 0, "apr": 0}
    profit = float(logs[-1].profit)
    index = []
    net_deposit = []
    for log in logs:
        index.append(datetime.fromtimestamp(log.timestamp))
        net_deposit.append(log.net_deposit)
    net_deposit_seires = pd.Series(net_deposit, index)
    avg_deposit = net_deposit_seires.resample("1s").last().fillna(method="ffill").mean()
    if avg_deposit > 0:
        roi = profit / avg_deposit
        days = (logs[-1].timestamp - logs[0].timestamp) / 86400
        apr = roi / days * 365
    else:
        roi = 0
        apr = 0
    return {"avg_deposit": avg_deposit, "profit": profit, "roi": roi, "apr": apr}

class DecimalEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Decimal):
            return str(obj)
        return json.JSONEncoder.default(self, obj)

def save_to_file(summary: dict, save_path: str) -> dict:
    path = pathlib.Path(save_path)
    if not path.exists():
        path.parent.mkdir(parents=True, exist_ok=True)

    with path.open("w") as fp:
        json.dump(summary, fp, indent=2, cls=DecimalEncoder)
    return summary

def save_summary(summary: dict, save_path: str) -> dict:
    save_to_file(summary, save_path)
    print(f"Save summary to {save_path}")
    return summary

def plot_logs(
    logs: List[LogState],
    hedge_trades: List[HedgeTrade],
    save_path: str,
    to_show: bool = False,
):
    if len(logs) == 0:
        return
    path = pathlib.Path(save_path)
    if not path.exists():
        path.parent.mkdir(parents=True, exist_ok=True)
    index = []
    basis = []
    position = []
    net_deposit = []
    profit = []
    for log in logs:
        index.append(datetime.fromtimestamp(log.timestamp))
        basis.append(log.basis)
        position.append(log.spot_position)
        net_deposit.append(log.net_deposit)
        profit.append(log.profit)

    trade_open_index = []
    trade_close_index = []
    trade_open = []
    trade_close = []
    for trade in hedge_trades:
        if trade.hedge_type == HedgeType.OPEN:
            trade_open_index.append(datetime.fromtimestamp(trade.timestamp))
            trade_open.append(trade.basis)
        else:
            trade_close_index.append(datetime.fromtimestamp(trade.timestamp))
            trade_close.append(trade.basis)

    fig, ax = plt.subplots(nrows=3, ncols=1, sharex=True, figsize=(12, 10))

    basis_ax = ax[0]
    position_ax = ax[1]
    profit_ax = ax[2]

    basis_ax.plot(index, basis, alpha=0.8, lw=1)
    offset = lambda p: transforms.ScaledTranslation(0, p / 72.0, fig.dpi_scale_trans)
    trans = basis_ax.transData
    basis_ax.scatter(
        trade_open_index,
        trade_open,
        c="r",
        marker="v",
        s=9,
        transform=trans + offset(5),
    )
    basis_ax.scatter(
        trade_close_index,
        trade_close,
        c="g",
        marker="^",
        s=9,
        transform=trans + offset(-5),
    )
    basis_ax.set_ylabel("basis")

    position_ax.plot(index, position)
    position_ax.set_ylabel("position")

    profit_ax.plot(index, profit)
    profit_ax.set_ylabel("profit")

    if to_show:
        plt.show()

    fig.savefig(save_path)
    print(f"Save plot to {save_path}")
    plt.close(fig)

# def plot_combined_model_logs(
#     logs: List[LogState],
#     hedge_trades: List[CombinedModelHedgeTrade],
#     save_path: str,
#     to_show: bool = True,
# ):
#     path = pathlib.Path(save_path)
#     if not path.exists():
#         path.parent.mkdir(parents=True, exist_ok=True)
#     index = []
#     basis = []
#     position = []
#     net_deposit = []
#     profit = []
#     for log in logs:
#         index.append(datetime.fromtimestamp(log.timestamp))
#         basis.append(log.basis)
#         position.append(log.spot_position)
#         net_deposit.append(log.net_deposit)
#         profit.append(log.profit)

#     both_open_index = []
#     both_open = []
#     m1_open_index = []
#     m1_open = []
#     m2_open_index = []
#     m2_open = []
#     both_close_index = []
#     both_close = []
#     m1_close_index = []
#     m1_close = []
#     m2_close_index = []
#     m2_close = []
#     one_open_the_other_close_index = []
#     one_open_the_other_close = []

#     for trade in hedge_trades:
#         if trade.hedge_type == CombinedModelHedgeType.BOTH_OPEN:
#             both_open_index.append(datetime.fromtimestamp(trade.timestamp))
#             both_open.append(trade.basis)
#         elif trade.hedge_type == CombinedModelHedgeType.MODEL1_OPEN:
#             m1_open_index.append(datetime.fromtimestamp(trade.timestamp))
#             m1_open.append(trade.basis)
#         elif trade.hedge_type == CombinedModelHedgeType.MODEL2_OPEN:
#             m2_open_index.append(datetime.fromtimestamp(trade.timestamp))
#             m2_open.append(trade.basis)
#         elif trade.hedge_type == CombinedModelHedgeType.BOTH_CLOSE:
#             both_close_index.append(datetime.fromtimestamp(trade.timestamp))
#             both_close.append(trade.basis)
#         elif trade.hedge_type == CombinedModelHedgeType.MODEL1_CLOSE:
#             m1_close_index.append(datetime.fromtimestamp(trade.timestamp))
#             m1_close.append(trade.basis)
#         elif trade.hedge_type == CombinedModelHedgeType.MODEL2_CLOSE:
#             m2_close_index.append(datetime.fromtimestamp(trade.timestamp))
#             m2_close.append(trade.basis)
#         elif trade.hedge_type == CombinedModelHedgeType.ONE_OPEN_THE_OTHER_CLOSE:
#             one_open_the_other_close_index.append(
#                 datetime.fromtimestamp(trade.timestamp)
#             )
#             one_open_the_other_close.append(trade.basis)

#     fig, ax = plt.subplots(nrows=3, ncols=1, sharex=True, figsize=(12, 10))

#     basis_ax: plt.Axes = ax[0]
#     position_ax: plt.Axes = ax[1]
#     profit_ax: plt.Axes = ax[2]

#     basis_ax.plot(index, basis, alpha=0.8, lw=1)
#     offset = lambda p: transforms.ScaledTranslation(0, p / 72.0, fig.dpi_scale_trans)
#     trans = basis_ax.transData
#     basis_ax.scatter(
#         both_open_index,
#         both_open,
#         c="darkgreen",
#         marker="v",
#         s=9,
#         transform=trans + offset(5),
#         label="both open",
#     )
#     basis_ax.scatter(
#         m1_open_index,
#         m1_open,
#         c="cyan",
#         marker="v",
#         s=9,
#         transform=trans + offset(5),
#         label="m1 open",
#     )
#     basis_ax.scatter(
#         m2_open_index,
#         m2_open,
#         c="dodgerblue",
#         marker="v",
#         s=9,
#         transform=trans + offset(5),
#         label="m2 open",
#     )
#     basis_ax.scatter(
#         both_close_index,
#         both_close,
#         c="b",
#         marker="^",
#         s=9,
#         transform=trans + offset(-5),
#         label="both close",
#     )
#     basis_ax.scatter(
#         m1_close_index,
#         m1_close,
#         c="orangered",
#         marker="^",
#         s=9,
#         transform=trans + offset(-5),
#         label="m1 close",
#     )
#     basis_ax.scatter(
#         m2_close_index,
#         m2_close,
#         c="magenta",
#         marker="^",
#         s=9,
#         transform=trans + offset(-5),
#         label="m2 close",
#     )
#     basis_ax.scatter(
#         one_open_the_other_close_index,
#         one_open_the_other_close,
#         c="b",
#         marker="X",
#         s=18,
#         label="bad",
#     )
#     basis_ax.set_ylabel("basis")
#     basis_ax.legend()

#     position_ax.plot(index, position)
#     position_ax.set_ylabel("position")

#     profit_ax.plot(index, profit)
#     profit_ax.set_ylabel("profit")

#     if to_show:
#         plt.show()

#     fig.savefig(save_path)
#     print(f"Save plot to {save_path}")
#     plt.close(fig)

def _check_backtest_attr(indicator_backtest: BaseIndicator):
    if not hasattr(indicator_backtest, "hedge_pair"):
        return False
    if not hasattr(indicator_backtest, "config"):
        return False
    if not hasattr(indicator_backtest, "kline_resolution"):
        return False
    return True

def get_trades_path(indicator_backtest: BaseIndicator):
    if not _check_backtest_attr(indicator_backtest):
        raise ValueError("Not backtest Indicator")
    return (
        indicator_backtest.config.save_dir
        + indicator_backtest.config.exchange
        + "/"
        + "merged_trades/"
        + FtxHedgePair.to_dir_name(indicator_backtest.hedge_pair.future)
        + "/"
        + str(indicator_backtest.config.start_timestamp)
        + "_"
        + str(indicator_backtest.config.end_timestamp)
        + ".parquet"
    )

def get_spot_klines_path(indicator_backtest: BaseIndicator):
    if not _check_backtest_attr(indicator_backtest):
        raise ValueError("Not backtest Indicator")
    return (
        indicator_backtest.config.save_dir
        + indicator_backtest.config.exchange
        + "/"
        + "kline/"
        + FtxHedgePair.to_dir_name(indicator_backtest.hedge_pair.spot)
        + "/"
        + str(indicator_backtest.config.start_timestamp)
        + "_"
        + str(indicator_backtest.config.end_timestamp)
        + "_"
        + str(indicator_backtest.kline_resolution.to_pandas_resample_rule())
        + ".parquet"
    )

def get_future_klines_path(indicator_backtest: BaseIndicator):
    if not _check_backtest_attr(indicator_backtest):
        raise ValueError("Not backtest Indicator")
    return (
        indicator_backtest.config.save_dir
        + indicator_backtest.config.exchange
        + "/"
        + "kline/"
        + FtxHedgePair.to_dir_name(indicator_backtest.hedge_pair.future)
        + "/"
        + str(indicator_backtest.config.start_timestamp)
        + "_"
        + str(indicator_backtest.config.end_timestamp)
        + "_"
        + str(indicator_backtest.kline_resolution.to_pandas_resample_rule())
        + ".parquet"
    )

def get_merged_klines_path(indicator_backtest: BaseIndicator):
    if not _check_backtest_attr(indicator_backtest):
        raise ValueError("Not backtest Indicator")
    return (
        indicator_backtest.config.save_dir
        + indicator_backtest.config.exchange
        + "/"
        + "merged_kline/"
        + FtxHedgePair.to_dir_name(indicator_backtest.hedge_pair.future)
        + "/"
        + str(indicator_backtest.config.start_timestamp)
        + "_"
        + str(indicator_backtest.config.end_timestamp)
        + "_"
        + str(indicator_backtest.kline_resolution.to_pandas_resample_rule())
        + ".parquet"
    )


""" Functions for downloading & analyzing wheels """

from __future__ import annotations
from datetime import datetime, timezone
import logging
from pathlib import Path
from tempfile import TemporaryDirectory
import traceback
from typing import Any
import requests
from wheel_inspect import inspect_wheel
from .app import emit_json_log
from .models import Wheel, db
from .util import USER_AGENT

log = logging.getLogger(__name__)

def process_queue(max_wheel_size: int | None = None) -> None:
    """
    Process all of the wheels returned by `Wheel.to_process()` one by one and
    store the results in the database.  If an error occurs, the traceback is
    stored as a `ProcessingError` for the wheel.  The database session is
    committed after each wheel in order to save memory.

    This function requires a Flask application context with a database
    connection to be in effect.

    :param int max_wheel_size: If set, only wheels this size or smaller are
        analyzed
    """
    start_time = datetime.now(timezone.utc)
    wheels_processed = 0
    bytes_processed = 0
    errors = 0
    with TemporaryDirectory() as tmpdir, requests.Session() as s:
        s.headers["User-Agent"] = USER_AGENT
        try:
            # This outer `try` block is so that stats are written to the
            # logfile even when the function is cancelled via Cntrl-C.
            for whl in Wheel.to_process(max_wheel_size=max_wheel_size):
                fpath = Path(tmpdir, whl.filename)
                try:
                    log.info("Downloading %s from %s ...", whl.filename, whl.url)
                    download(s, whl.url, fpath)
                    about = process_wheel(
                        path=fpath,
                        size=whl.size,
                        md5=whl.md5,
                        sha256=whl.sha256,
                    )
                    whl.set_data(about)
                    # Some errors in inserting data aren't raised until we
                    # actually try to insert by calling commit(), so include
                    # the commit() under the `try`.
                    db.session.commit()
                except Exception:
                    # rollback() needs to be called before log.exception() or
                    # else SQLAlchemy gets all complainy.
                    db.session.rollback()
                    log.exception("Error processing %s", whl.filename)
                    whl.add_error(traceback.format_exc())
                    db.session.commit()
                    errors += 1
                finally:
                    fpath.unlink(missing_ok=True)
                wheels_processed += 1
                bytes_processed += whl.size
        finally:
            end_time = datetime.now(timezone.utc)
            emit_json_log(
                "process_queue.log",
                {
                    "op": "process_queue",
                    "start": str(start_time),
                    "end": str(end_time),
                    "wheels": wheels_processed,
                    "bytes": bytes_processed,
                    "errors": errors,
                },
            )

def process_wheel(path: Path, size: int, md5: str | None, sha256: str | None) -> dict:
    """
    Process the wheel at ``path``.  The wheel is analyzed with
    `inspect_wheel()`, and its size & digests are checked against ``size``,
    ``md5``, and ``sha256`` (provided by PyPI) to verify download integrity.

    :return: the results of the call to `inspect_wheel()`
    """
    log.info("Inspecting %s ...", path.name)
    about: dict[str, Any] = inspect_wheel(path)
    if about["file"]["size"] != size:
        log.error(
            "Wheel %s: size mismatch: PyPI reports %d, got %d",
            size,
            about["file"]["size"],
        )
        raise ValueError(
            f'Size mismatch: PyPI reports {size}, got {about["file"]["size"]}'
        )
    for alg, expected in [("md5", md5), ("sha256", sha256)]:
        if expected is not None and expected != about["file"]["digests"][alg]:
            log.error(
                "Wheel %s: %s hash mismatch: PyPI reports %s, got %s",
                alg,
                expected,
                about["file"]["digests"][alg],
            )
            raise ValueError(
                f"{alg} hash mismatch: PyPI reports {expected},"
                f' got {about["file"]["digests"][alg]}'
            )
    log.info("Finished inspecting %s", path.name)
    return about

def download(s: requests.Session, url: str, path: Path) -> None:
    r = s.get(url, stream=True)
    r.raise_for_status()
    with path.open("wb") as fp:
        for chunk in r.iter_content(65535):
            fp.write(chunk)


import numpy as np
import pytest
import torch

from saliency_metrics.metrics import RoarPerturbation

@pytest.fixture
def dummy_img_and_smap():
    # two single-channel images, the first one has channel mean of 5.0, and the second one has channel mean of 15.0
    img_1 = torch.arange(1, 10, dtype=torch.float32).reshape(1, 3, 3)
    img_2 = torch.arange(11, 20, dtype=torch.float32).reshape(1, 3, 3)
    img = torch.stack([img_1, img_2], dim=0)
    # saliency maps
    smap_1 = np.arange(1, 10, dtype=float).reshape(3, 3)
    smap_2 = np.arange(11, 20, dtype=float).reshape(3, 3)
    smap = np.stack([smap_1, smap_2], axis=0)
    yield img, smap

def test_init(dummy_img_and_smap):
    for invalid_fraction in (-0.1, 1.1):
        with pytest.raises(ValueError, match="top_fraction should"):
            _ = RoarPerturbation(top_fraction=invalid_fraction)

    top_fraction = 0.1

    ptb_1 = RoarPerturbation(top_fraction, mean=None)
    assert ptb_1.quantile == 0.9
    assert not ptb_1._has_mean
    with pytest.raises(AttributeError):
        ptb_1.get_buffer("_mean")

    ptb_2 = RoarPerturbation(top_fraction, mean=[0.0, 0.0, 0.0])
    assert ptb_2.quantile == 0.9
    assert ptb_2._has_mean
    torch.testing.assert_allclose(ptb_2.get_buffer("_mean"), torch.zeros((3,), dtype=torch.float32))

@pytest.mark.parametrize("top_fraction", [0.0, 0.2, 1.0])
@pytest.mark.parametrize(
    "mean",
    [
        (100,),
        None,
    ],
)
def test_perturb_and_forward(dummy_img_and_smap, top_fraction, mean):
    img, smap = dummy_img_and_smap

    ptb = RoarPerturbation(top_fraction, mean)

    if mean is not None:
        if top_fraction == 1.0:
            expected_ptb_out = torch.full_like(img, 100.0)
        elif top_fraction == 0.0:
            expected_ptb_out = img
        else:
            out = img.clone()
            out[:, :, 2, 1:] = 100
            expected_ptb_out = out
    else:
        if top_fraction == 1.0:
            expected_ptb_out = torch.stack(
                [torch.full((1, 3, 3), 5.0, dtype=torch.float32), torch.full((1, 3, 3), 15.0, dtype=torch.float32)],
                dim=0,
            )
        elif top_fraction == 0.0:
            expected_ptb_out = img
        else:
            out = img.clone()
            out[0, :, 2, 1:] = 5.0
            out[1, :, 2, 1:] = 15.0
            expected_ptb_out = out

    expected_forward_out = expected_ptb_out
    torch.testing.assert_allclose(ptb.perturb(img, smap), expected_ptb_out)
    torch.testing.assert_allclose(ptb.forward(img, smap), expected_forward_out)


from math import ceil

def solution(progresses, speeds):
    answer = []
    open = []
    for i in range(len(progresses)):
        tmp = ceil((100 - progresses[i]) / speeds[i])
        open.append(tmp)

    stand = open[0]
    tmp = 1
    for i in range(1, len(open)):
        if i == len(open)-1:
            if open[i] <= stand:
                tmp += 1
                answer.append(tmp)
                break
            elif open[i] > stand:
                answer.append(tmp)
                answer.append(1)
                break
        if open[i] <= stand:
            tmp += 1
        elif open[i] > stand:
            answer.append(tmp)
            stand = open[i]
            tmp = 1

    return answer

progresses = [93, 30, 55]
speeds = [1, 30, 5]
print(solution(progresses, speeds))

progresses = [95, 90, 99, 99, 80, 99]
speeds = [1, 1, 1, 1, 1, 1]
print(solution(progresses, speeds))


import json
import csv
from parser import get_people_data, get_book_data
from sorting import get_equals_books, add_books_to_people

people_list = []
with open("users.json", "r") as file:
    people = json.load(file)
for person in people:
    people_list.append(get_people_data(person))

books_list = []
with open("books.csv", "r") as file:
    books = list(csv.DictReader(file))
for book in books:
    books_list.append(get_book_data(book))

equals_books_gen = get_equals_books(books_list, len(people_list))

people_with_books = []
for person in people_list:
    people_with_books.append(add_books_to_people(person, next(equals_books_gen)))

with open("result.json", "w") as outfile:
    json.dump(people_with_books, outfile, indent=4)


import customtkinter
from tkinter import *

customtkinter.set_appearance_mode('dark')
customtkinter.set_default_color_theme('blue')

root = customtkinter.CTk()
root.geometry('500x500')

vertical = Scale(root, from_=0, to=400, sliderlength=10,length=200)
vertical.pack(padx=10,pady=10)

def slide():
    lbl = customtkinter.CTkLabel(root, text=horizontal.get()).pack()
    root.geometry(str(horizontal.get()) + 'x' + str(vertical.get()))

horizontal = Scale(root, from_=0, to=400, orient=HORIZONTAL,length=300)
horizontal.pack()

lbl = customtkinter.CTkLabel(root, text=horizontal.get()).pack()

btn = customtkinter.CTkButton(root,text='Click Me',command=slide).pack(padx=10,pady=10)
root.mainloop()


def list_sort():
  #a. create a list o f7 elements and append an obj 80 to the list
  l1 = [10,20,30,40,50,60,70]
  print ("Original list: ", l1)
  l1.append(80)
  print("after appending 80 to the list: ", l1)

  #b. insert 100 at 4th position
  l1.insert(3,100)
  print ("After inserting 100 in 4th position: ", l1)

  #c. sort and pirnt all elem
  l1.sort()
  print("After sorting : ", l1)

  l2 = sorted(l1,key = int, reverse = True)
  print("printing the sorted elem list2: ", l2)

  #c. delete last  3 elem
  l2.pop(len(l2)-1)
  l2.pop(len(l2)-1)
  l2.pop(len(l2)-1)
  print("deleting last 3 elems", l2)


def securityChecker():

    valid_usernames = ('jimbo', 'giltson98', 'derekf', 'WhatSup', 'NicolEye',
                   'swei45','BaseInterpreterInterface', 'BaseStdIn', 'Command', 'ExecState',
                   'InteractiveConsole', 'InterpreterInterface', 'StartServer', 'bob')

    user_username = input("Username: ")

    if user_username in valid_usernames:
        print("Access Granted")
        generate_income_report()

    else:
        print("Access Denied")

def generate_income_report():
    incomes = []
    error_check = False

    #Error Handling
    while error_check is False:
        try:
            number_of_months = int(input("How many number_of_months? "))

            while number_of_months <= 0:
                print("Please input positive number of months!")
                number_of_months = int(input("How many number_of_months? "))

            error_check = True

        except ValueError:
            print("Number of months must be a number!")

    for month in range(1, number_of_months + 1):
        income = float(input("Enter income for month {} ".format(month)))
        incomes.append(income)

    #Call print_report function
    print_report(incomes, number_of_months, income, month)

def print_report(incomes, number_of_months, income, month):
    print("\nIncome Report\n-------------")
    total = 0

    for month in range(1, number_of_months + 1):
        income = incomes[month - 1]
        total += income
        print("Month {:2} - Income: ${:10.2f} Total: ${:10.2f}".format(month, income, total))

securityChecker()


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Mon May 11 11:59:38 2020

@author: williamglazer
"""

import os
import numpy as np
from constants import DATA_DIMENSIONS
cwd = os.getcwd()

def parse(line):
    """

    Parameters
    ----------
    line : string
        string of: user_id, ittem_id, rating, timestamp
        split by tab with a trailing newline.

    Returns
    -------
    rating_link_array_no_timestamp : int[][3]
        array of [user_id, item_id, rating]
        where
            user_id in {1..943}
            item_id in {1..1682}
            rating  in {1..5}.

    """
    line_no_trailing_char = line.rstrip('\n')
    rating_link_array = line_no_trailing_char.split('\t')
    rating_link_array_no_timestamp = rating_link_array[:-1]
    int_link_array = [int(rating_link_array_no_timestamp[0])-1,
                      int(rating_link_array_no_timestamp[1])-1,
                      int(rating_link_array_no_timestamp[2])
                      ]
    return int_link_array

def create_matrix_from_ratings(links):
    """

    Parameters
    ----------
    links : int[][3]
        array of [user_id, item_id, rating]
        where
            user_id in {1..943}
            item_id in {1..1682}
            rating  in {1..5}.

    Returns
    -------
    R : np.matrix(int, int)
        matrix of [users, items].

    """

    R = np.zeros((
        DATA_DIMENSIONS['users'],
        DATA_DIMENSIONS['items']))
    for u, i, r_ui in links:
        R[u, i] = r_ui
    return R


import os
import csv

def split_csv(source_filepath, dest_folder, split_file_prefix,
                records_per_file):
    """
    Split a source csv into multiple csvs of equal numbers of records,
    except the last file.

    Includes the initial header row in each split file.

    Split files follow a zero-index sequential naming convention like so:

        `{split_file_prefix}_0.csv`
    """
    if records_per_file <= 0:
        raise Exception('records_per_file must be > 0')

    with open(source_filepath, 'r') as source:
        reader = csv.reader(source)
        headers = next(reader)

        file_idx = 0
        records_exist = True

        while records_exist:

            i = 0
            target_filename = '{}_{}.csv'.format(split_file_prefix, file_idx)
            target_filepath = os.path.join(dest_folder, target_filename)

            with open(target_filepath, 'w') as target:
                writer = csv.writer(target)

                while i < records_per_file:
                    if i == 0:
                        writer.writerow(headers)

                    try:
                        writer.writerow(next(reader))
                        i += 1
                    except:
                        records_exist = False
                        break

            if i == 0:
                # we only wrote the header, so delete that file
                os.remove(target_filepath)

            file_idx += 1

split_csv('lead0.csv', './','lead_part_',10000)


import os
import cv2
import numpy as np
import time
try:
    from tflite_runtime.interpreter import Interpreter
except:
    from tensorflow.lite.python.interpreter import Interpreter

fps = ""
detectfps = ""
framecount = 0
detectframecount = 0
time1 = 0
time2 = 0

if __name__ == '__main__':

    camera_index  = 0
    camera_width  = 416
    camera_height = 416

    model_scale = 320

    # Tensorflow Lite
    interpreter = Interpreter(model_path='u2netp_{}x{}_float32.tflite'.format(model_scale, model_scale), num_threads=4)
    interpreter.allocate_tensors()
    input_details = interpreter.get_input_details()[0]['index']
    output_details = interpreter.get_output_details()[0]['index']


"""
This contains the EMOD specific manifest.  This inherits from the ManifestFile base class.

The reintegration code here is both model and version specific.  As such, each version should
have it's own reintegration code and the reintegration method should select, based on a keyword
in the manifest file, which method to use.
"""

import json
from manifest import ManifestFile
from json_merging.merge_tools import merge_list

class EMODManifestFile(ManifestFile):
    """
    This is the EMOD Specific manifest file.

    This inherits the ability to read in from JSON.  From that, it can split out fully
    specified config and campaign files to be used by EMOD as inputs.

    The code that lives in this class is specifically related to splitting executions
    back out from the manifest file.
    """

    config = None           #: Config dictionary
    campaign = None         #: Campaign dictionary
    template_files = [      #: The required template files for an EMOD simulation
        'config.json',
        'campaign.json'
    ]

    @classmethod
    def split_executions_15(cls, manifest, template):
        """
        This will merge the changes from executions into a config and campaign file from a manifest
        for EMOD version 1.5.

        :params manifest: ManifestFile instance
        :params template: Dictionary containing the config.json and campaign.json
        :yields: Tuples containing (execution_id, num_replications, execution_config.json, execution_campaign.json)
        """
        for execution in manifest.executions:
            exec_id = execution.id
            exec_changes = execution.jcd.jcdict
            template = merge_list(template, exec_changes)
            yield exec_id, execution.replications, json.dumps(template['config.json']), json.dumps(template['campaign.json'])

    def split_executions(self):
        """
        This generator method will split the manifest file into individual executions and return execution id,
        config.json (as json), and campaign.json (as json).

        This first checks to see if a manifest file has been created or read in with templates, executions,
        and a run.  It also checks to make sure the required template files are in the template dict.

        Before returning specific executions, we merge in the run level changes.
        """
        if self.run is None or self.executions == [] or self.templates == {}:
            raise ValueError("You must read or create a manifest file with runs and executions")

        if not all(x in self.templates.keys() for x in self.template_files):
            raise ValueError("Template must contain keys for config.json and campaign.json")

        # -------- We create a single dictionary that holds both as the xpath specified within EMOD manifests
        # -------- refer to the file as the first path.
        template = dict()
        template['config.json'] = json.loads(self.templates['config.json'])
        template['campaign.json'] = json.loads(self.templates['campaign.json'])

        self.version='1.5'
        rlcl = self.run.jcd.jcdict
        template = merge_list(template, rlcl)

        split_dict = {
            '1.5': self.split_executions_15
        }

        for execution_tuple in split_dict[self.version](self, template):
            yield execution_tuple


from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('index.html', views.contact2, name='contact2'),
    path('seven.html', views.seven, name='seven'),

    path('about.html', views.about, name='about'),
    path('car.html', views.car, name='car'),
    path('contact.html', views.contact, name='contact'),
    path('detail.html', views.detail, name='detail'),
    path('service.html', views.service, name='service'),
    path('message.html', views.contact, name="contact"),

    path('meetings.html', views.meetings, name='meetings'),
    path('meeting-details.html', views.meetingdetails, name='meetingdetails'),
]


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

import os
from typing import Any, Dict, Optional, Text, Union

import absl
from airflow import models

from tfx.orchestration import pipeline
from tfx.orchestration import tfx_runner
from tfx.orchestration.airflow import airflow_component
from tfx.orchestration.config import config_utils
from tfx.orchestration.config import pipeline_config

class AirflowPipelineConfig(pipeline_config.PipelineConfig):
  """Pipeline config for AirflowDagRunner."""

  def __init__(self, airflow_dag_config: Dict[Text, Any] = None, **kwargs):
    """Creates an instance of AirflowPipelineConfig.

    Args:
      airflow_dag_config: Configs of Airflow DAG model. See
        https://airflow.apache.org/_api/airflow/models/dag/index.html#airflow.models.dag.DAG
          for the full spec.
      **kwargs: keyword args for PipelineConfig.
    """

    super(AirflowPipelineConfig, self).__init__(**kwargs)
    self.airflow_dag_config = airflow_dag_config or {}

class AirflowDagRunner(tfx_runner.TfxRunner):
  """Tfx runner on Airflow."""

  def __init__(self,
               config: Optional[Union[Dict[Text, Any],
                                      AirflowPipelineConfig]] = None):
    """Creates an instance of AirflowDagRunner.

    Args:
      config: Optional Airflow pipeline config for customizing the launching of
        each component.
    """
    if config and not isinstance(config, AirflowPipelineConfig):
      absl.logging.warning(
          'Pass config as a dict type is going to deprecated in 0.1.16. Use AirflowPipelineConfig type instead.',
          PendingDeprecationWarning)
      config = AirflowPipelineConfig(airflow_dag_config=config)
    super(AirflowDagRunner, self).__init__(config)

  def run(self, tfx_pipeline: pipeline.Pipeline):
    """Deploys given logical pipeline on Airflow.

    Args:
      tfx_pipeline: Logical pipeline containing pipeline args and components.

    Returns:
      An Airflow DAG.
    """

    # Merge airflow-specific configs with pipeline args
    airflow_dag = models.DAG(
        dag_id=tfx_pipeline.pipeline_info.pipeline_name,
        **self._config.airflow_dag_config)
    if 'tmp_dir' not in tfx_pipeline.additional_pipeline_args:
      tmp_dir = os.path.join(tfx_pipeline.pipeline_info.pipeline_root, '.temp',
                             '')
      tfx_pipeline.additional_pipeline_args['tmp_dir'] = tmp_dir

    component_impl_map = {}
    for tfx_component in tfx_pipeline.components:

      (component_launcher_class,
       component_config) = config_utils.find_component_launch_info(
           self._config, tfx_component)
      current_airflow_component = airflow_component.AirflowComponent(
          airflow_dag,
          component=tfx_component,
          component_launcher_class=component_launcher_class,
          pipeline_info=tfx_pipeline.pipeline_info,
          enable_cache=tfx_pipeline.enable_cache,
          metadata_connection_config=tfx_pipeline.metadata_connection_config,
          beam_pipeline_args=tfx_pipeline.beam_pipeline_args,
          additional_pipeline_args=tfx_pipeline.additional_pipeline_args,
          component_config=component_config)
      component_impl_map[tfx_component] = current_airflow_component
      for upstream_node in tfx_component.upstream_nodes:
        assert upstream_node in component_impl_map, ('Components is not in '
                                                     'topological order')
        current_airflow_component.set_upstream(
            component_impl_map[upstream_node])

    return airflow_dag


from google_images_download import google_images_download   #importing the library
import json
import pandas as pd

response = google_images_download.googleimagesdownload()

if __name__ == "__main__":
    filepath = 'data/raw/100VietnameseCelebName.txt'
    df = pd.DataFrame(columns=['Name', 'Pic'])

    name_list = pd.read_csv(filepath, header=None)
    name_list.columns = ['name']
    # name_list.apply(lambda x: x.strip())

    for _, row in name_list.iterrows():
        name = row.values[0]
        paths, err = response.download({"keywords": name, "limit": 10, 'format': 'png'})
        a = json.dumps(paths)
        d = json.loads(a)
        temp = []
        for i in range(0, len(d[name])):
            temp.append(name)
        data = {'Name': temp, 'Pic': d[name]}
        df = df.append(data, ignore_index=True)

    df.to_csv('celeb.csv')


from code.employee import Employee
from code.company import *

if __name__ == "__main__":
	july = Employee("July", 1, "CEO", 99999999)
	# print(july.get_info())
	zewei = Employee("Zewei", 2, "Lecturer", 1, july)
	# print(zewei.get_info())

	c = Company("Julyedu")
	c.hire(july)
	c.hire(zewei)

	han = Employee("Han Xiaoyang", 3, "Lecturer", 1000000, july)
	c.hire(han)

	print(c.get_info())

	print("Firing Zewei!!!")
	c.fire(zewei)
	print(c.get_info())

	print("Firing Zewei!!!")
	c.fire(zewei)
	print(c.get_info())

	c.hire(zewei)
	print(c.get_info())

	# sublime
	# namespace


import requests
import os
import pickle

if __name__ == "__main__":
    os.environ['NO_PROXY'] = '127.0.0.1'
    response = requests.get("http://localhost:5000/ping")
    print(response.text)
    print(response.content)
    print(response.json()[0])
    responses = pickle.loads(response.content)
    print(responses)

    # url = "http://127.0.0.1:5000/evaluate-model"
    # data = {'model_name': 'test', 'data': 'here'}
    #
    # response = requests.post(url, data)
    # print(response.text)


import nltk
from nltk.stem.lancaster import LancasterStemmer
stemmer = LancasterStemmer()

import numpy
import tensorflow as tf
import tflearn
import random
import json

with open("topics.json") as file:
    data = json.load(file)

    words = []
    labels = []
    list_x = []
    list_y = []

    for topic in data["topics"]:
        for pattern in topic["patterns"]:
            wrds = nltk.word_tokenize(pattern)
            words.extend(wrds)
            list_x.append(wrds)
            list_y.append(topic["tag"])

        if topic["tag"] not in labels:
            labels.append(topic["tag"])

    words = [stemmer.stem(w.lower()) for w in words]
    words = sorted(list(set(words)))

    labels = sorted(labels)

    training = []
    output = []

    empty = [0 for _ in range(len(labels))]

    for x, list in enumerate(list_x):
        bag = []

        wrds = [stemmer.stem(w.lower()) for w in list if w != "?"]

        for w in words:
            if w in wrds:
                bag.append(1)
            else:
                bag.append(0)

        output_x = empty[:]
        output_x[labels.index(list_y[x]) ] = 1

        training.append(bag)
        output.append(output_x)

    training = numpy.array(training)
    output = numpy.array(output)

tf.reset_default_graph()

net = tflearn.input_data(shape=[None, len(training[0])])
net = tflearn.fully_connected(net, 16)
net = tflearn.fully_connected(net, 16)
net = tflearn.fully_connected(net, 8)
net = tflearn.fully_connected(net, len(output[0]), activation="softmax")
net = tflearn.regression(net)

model = tflearn.DNN(net)

model.fit(training, output, n_epoch=1000, batch_size=10, show_metric=True)
model.save("model.tflearn")

def bag_of_words(s, words):
    bag = [0 for _ in range(len(words))]

    s_words = nltk.word_tokenize(s)
    s_words = [stemmer.stem(word.lower()) for word in s_words]

    for se in s_words:
        for i, w in enumerate(words):
            if w == se:
                bag[i] = 1

    return numpy.array(bag)

def chat():
    print("Hi, I'm RamsayBot \n Type 'quit' to leave ")
    while True:
        inp = input("You: ")
        if inp.lower() == "quit":
            break

        results = model.predict([bag_of_words(inp, words)])
        results_index = numpy.argmax(results)
        tag = labels[results_index]

        for tg in data["topics"]:
            if tg['tag'] == tag:
                responses = tg['responses']

        print(random.choice(responses))

chat()


# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, val=0, left=None, right=None):
#         self.val = val
#         self.left = left
#         self.right = right
class Solution:
    def boundaryOfBinaryTree(self, root: Optional[TreeNode]) -> List[int]:
        left_boundary = []
        right_boundary = []
        leaves = []

        def preorder(node, flag):
            if not node:
                return
            if isRightBoundary(flag):
                right_boundary.append(node.val)
            elif isLeftBoundary(flag) or isRoot(flag):
                left_boundary.append(node.val)
            elif isLeaf(node):
                leaves.append(node.val)

            if node.left:
                preorder(node.left, leftFlag(node, flag))
            if node.right:
                preorder(node.right, rightFlag(node, flag))

        def isLeaf(node):
            return not node.right and not node.left
        def isRightBoundary(flag):
            return flag == 2
        def isLeftBoundary(flag):
            return flag == 1
        def isRoot(flag):
            return flag == 0
        def leftFlag(node, flag):
            if isLeftBoundary(flag) or isRoot(flag):
                return 1
            if isRightBoundary(flag) and not node.right:
                return 2
            return 3
        def rightFlag(node, flag):
            if isRightBoundary(flag) or isRoot(flag):
                return 2
            if isLeftBoundary(flag) and not node.left:
                return 1
            return 3

        preorder(root, 0)
        left_boundary.extend(leaves)
        left_boundary.extend(right_boundary[::-1])
        return left_boundary


"""
Day 01
Given a list of numbers, find a pair that sums to 2020. Return the product of those numbers.
"""

import itertools
from typing import List
from functools import reduce
from operator import mul

target_value = 2020

# Use itertools.combinataions to produce a list of all pairs

def solve_two(input_list: List[int],
              target: int = target_value,
              ) -> int:
    for c in itertools.combinations(input_list, 2):
        if c[0] + c[1] == target_value:
            print(f"{c[0]} + {c[1]} == {target_value}")
            print(f"{c[0]} * {c[1]} => {c[0] * c[1]}")
            return c[0] * c[1]

def product(inputs: List[int]) -> int:
    """We can use the built-in `sum` to sum a list,
       but there is no corresponding function for product.

       Refactor: Using functools.reduce and operator mul, we
       can do this more succinctly: reduce(mul, inputs)
    """
    accumulator = 1  # safe for multipliction
    for i in inputs:
        accumulator *= i
    return accumulator

def solve_generic(input_list: List[int],
                  target: int = target_value,
                  num_elements: int = 2,
                  ) -> int:
    """Solve in a more generic way that lets us specify
       how many elements to use in our solution.
    """
    for c in itertools.combinations(input_list, num_elements):
        if sum(c) == target_value:
            print(c)
            return reduce(mul, c)

if __name__ == "__main__":
    with open('d01.input', 'r') as f:
        puzzle_input: List[int] = [int(s) for s in f.readlines()]

    # print(solve_two(puzzle_input))
    print(solve_generic(puzzle_input, target_value, 2))
    print(solve_generic(puzzle_input, target_value, 3))


import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import seaborn as sb  # visualization

# Load data into pandas DataFrame
dataSet = pd.read_csv(
    "/home/ivan/Desktop/ArtificialIntelligence/Lab3/apartmentComplexData.txt",
    header=None,
    usecols=[2, 3, 4, 5, 6, 8],
    names=[
        "complexAge",
        "totalRooms",
        "totalBedrooms",
        "complexInhabitants",
        "apartmentsNr",
        "medianComplexValue",
    ],
)

plt.subplot(2, 3, 1)
plt.scatter(dataSet["medianComplexValue"], dataSet["complexAge"], color="red")
plt.title("Dependenta dintre pret si virsta")
plt.ylabel("Virsta bloc")
plt.xlabel("Pret in U/M")
plt.subplot(2, 3, 2)
plt.scatter(dataSet["medianComplexValue"], dataSet["totalRooms"], color="blue")
plt.title("Dependenta dintre pret si nr de camere")
plt.ylabel("Nr. de camere")
plt.xlabel("Pret in U/M")
plt.subplot(2, 3, 3)
plt.scatter(dataSet["medianComplexValue"], dataSet["totalBedrooms"], color="orange")
plt.title("Dependenta dintre pret si nr camere sanitare")
plt.ylabel("Nr camere sanitare")
plt.xlabel("Pret in U/M")
plt.subplot(2, 3, 4)
plt.scatter(
    dataSet["medianComplexValue"], dataSet["complexInhabitants"], color="yellow"
)
plt.title("Dependenta dintre pret si nr de locuitori in bloc")
plt.ylabel("Locuitori in bloc")
plt.xlabel("Pret in U/M")
plt.subplot(2, 3, 5)
plt.scatter(dataSet["medianComplexValue"], dataSet["apartmentsNr"], color="green")
plt.title("Dependenta dintre pret si nr de partamente in bloc")
plt.ylabel("Nr apartamente in bloc")
plt.xlabel("Pret in U/M")
plt.subplot(2, 3, 6)
sb.distplot(dataSet["medianComplexValue"], color="maroon")
plt.title("Distributia pretului")
plt.xlabel("Pret in U/M")
plt.subplot(2, 3, 6)
plt.show()


from typing import (
    List,
    Tuple,
    Type,
    Union,
)

import datetime

from sqlalchemy import (
    Boolean,
    Column,
    DateTime,
    Integer,
    MetaData,
)
from sqlalchemy.orm import declarative_base

from xquery.config import CONFIG as C

Base = declarative_base(
    metadata=MetaData(
        schema=C["DB_SCHEMA"],
    ),
)

TDBObjs = Union[List[Base], List[Tuple[Type[Base], List[dict]]]]

class BaseModel(object):
    id = Column(Integer, primary_key=True, unique=True, autoincrement=True)

class BaseModelAddDelete(BaseModel):
    date_added = Column(DateTime, default=datetime.datetime.utcnow)
    date_updated = Column(DateTime, default=datetime.datetime.utcnow, onupdate=datetime.datetime.utcnow)
    date_deleted = Column(DateTime, default=None)
    deleted = Column(Boolean, default=False)


import numpy as np
import pylab as plt
import seaborn as sns; sns.set()
import pickle

import sparseRRR

def preprocess(data):
    X = data['counts'][:,data['mostVariableGenes']] / np.sum(data['counts'], axis=1) * 1e+6
    X = np.array(X)
    X = np.log2(X + 1)
    X = X - np.mean(X, axis=0)
    X = X / np.std(X, axis=0)

    Y = data['ephys']
    Y = Y - np.mean(Y, axis=0)
    Y = Y / np.std(Y, axis=0)

    return (X,Y)

data = pickle.load(open('/home/fank/Documents/patch-seq-rrr/data/scala2020.pickle', 'rb'))

X,Y = preprocess(data)
genes = data['genes'][data['mostVariableGenes']]

print('Shape of X:', X.shape, '\nShape of Y:', Y.shape)

w,v = sparseRRR.relaxed_elastic_rrr(X, Y, rank=2, lambdau=.4, alpha=1)

print('\nGenes selected: {}'.format(np.sum(w[:,0]!=0)))
print(', '.join(genes[w[:,0]!=0]))

sparseRRR.bibiplot(X, Y, w, v, titles = ['RNA expression', 'Electrophysiology'],
                   cellTypes=data['ttype'],
                   cellTypeColors=data['colors'],
                   YdimsNames=data['ephysNames'],
                   XdimsNames=genes)


from app import db

class LoanModel(db.Model):
    __tablename__ = 'loan'
    id = db.Column(db.Integer, primary_key=True)
    user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
    friend_id = db.Column(db.Integer, db.ForeignKey('friend.id'), nullable=False)
    item_id = db.Column(db.Integer, db.ForeignKey('item.id'), nullable=False)
    loan_type = db.Column(db.Integer, default=0, nullable=False)
    description = db.Column(db.String(30), nullable=True)
    status = db.Column(db.Integer, default=1, nullable=False)

    def __init__(self, user_id, friend_id, item_id, loan_type, description, status=1):
        self.user_id = user_id
        self.friend_id = friend_id
        self.item_id = item_id
        self.loan_type = loan_type
        self.description = description
        self.status = status

    def save_to_db(self):
        db.session.add(self)
        db.session.commit()

    def delete_from_db(self):
        db.session.delete(self)
        db.session.commit()

    def describe(self):
        return {
            'id': self.id,
            'user_id': self.user_id,
            'user_name': self.user.name,
            'friend_id': self.friend_id,
            'friend_name': self.friend.name,
            'item_id': self.item_id,
            'item_name': self.item.name,
            'loan_type': 'friend_to_user' if self.loan_type == 0 else 'user_to_friend',
            'description': self.description,
            'status': 'active' if self.status == 1 else 'inactive'
        }

    @classmethod
    def find_all(cls, user_id=None):
        if user_id:
            return cls.query.filter_by(user_id=user_id)
        return cls.query.all()

    @classmethod
    def find_by_name_and_user_id(cls, name, user_id):
        return cls.query.filter_by(name=name, user_id=user_id).first()

    @classmethod
    def find_by_id(cls, id):
        return cls.query.filter_by(id=id).first()


# -*- coding: utf-8 -*-
"""
Created on Mon Oct  5 09:58:50 2020
Gets a 5 digit zip code and converts the zip code to a barcode
@author: mbrothen
"""

def main():
    def getDigit():
        # Gets the barcode from user
        validZip = False
        while not validZip:
            zipCode = input("Enter a 5 digit zipcode: ")
            try:
                # Verify int, ask again if not
                int(zipCode)
                if len(zipCode) != 5:
                    # Verify number is appropriate length, ask again if not
                    print("Make sure zipcode is 5 digits")
                    validZip = False
                else:
                    validZip = True
            except ValueError:
                print("Enter a number")
                validZip = False
        return zipCode

    def printDigit(d):
        # Output barcode for specific number
        conversionTable = [
            [1, 1, 0, 0, 0],  # 0
            [0, 0, 0, 1, 1],  # 1
            [0, 0, 1, 0, 1],  # 2
            [0, 0, 1, 1, 0],  # 3
            [0, 1, 0, 0, 1],  # 4
            [0, 1, 0, 1, 0],  # 5
            [0, 1, 1, 0, 0],  # 6
            [1, 0, 0, 0, 1],  # 7
            [1, 0, 0, 1, 0],  # 8
            [1, 0, 1, 0, 0],  # 9
            ]
        for i in conversionTable[int(d)]:
            if i == 1:
                print("|", end="")
            elif i == 0:
                print(":", end="")

    def checkDigit(zipCode):
        # Calculate the check digit
        total = 0
        checkDigit = 0
        for d in zipCode:
            total += int(d)
        while total % 10 != 0:
            total += 1
            checkDigit += 1
        printDigit(checkDigit)

    def printEncodedBarcode(zipCode):
        # Print the barcode
        # Print leading bar
        print(str(zipCode) + " is: ")
        # Print frame bar
        print("|", end="")
        # interate through barcode to print each digit
        for d in zipCode:
            printDigit(d)
        # Calculate and print check digit
        checkDigit(zipCode)
        # Print trailing frame bar
        print("|")

    zipCode = getDigit()
    printEncodedBarcode(zipCode)

main()


from tkinter import *

window = Tk()
window.geometry("500x500+10+10")
def function(event):
    print("mouse event")

label = Label(window, text="click me")

label.pack()

label.bind("<Double-Enter>", function)
window.mainloop()


import multiprocessing
import subprocess
import psutil
import time
import argparse
from random import randrange

start_time = time.time()

def parse_args():
    parser = argparse.ArgumentParser(description='Process some integers.')

    parser.add_argument("--free-space", action="store", type=int, required=True,
                        dest="free_space", help="X - how many free MB?")

    parser.add_argument("--number-of-files", action="store", type=int, required=True,
                    dest="number_of_files", help="Z - how many file do you want to create")

    parser.add_argument("--size", action="store", type=int, required=True,
                        dest="size", help="Y - which size file to create")

    arguments = parser.parse_args()

    return arguments

def run(cmd):
    exec_cmd = subprocess.Popen(
        cmd,
        shell=True,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        universal_newlines=True,
    )
    a_stdout, a_stderr = exec_cmd.communicate()
    errcode = exec_cmd.returncode
    return a_stdout, errcode, a_stderr

def run_in_parallel(files, size, mountpoint):
    if files > 0:
        # Don't create file in "/"
        if mountpoint != "/":
            pool_args = [{'cmd': f"dd if=/dev/urandom of={mountpoint}/tmp{randrange(2000)}.txt bs={size}MB count=1"} for _ in range(files)]
            with multiprocessing.Pool(len(pool_args)) as p:
                p.map(mp_worker, pool_args)
    else:
        print(f"nothing to create, probably you wanted to create 0 files?")

def mp_worker(args):
    print (f"running {args['cmd']}")
    res = run(args['cmd'])
    out, code, err = res[0], res[1], res[2]
    if code != 0:
        print(f"[ERROR] - {err}")
    if out:
        print(f"[Success] - {out}")

def run_on_partition(X, Z, Y):
    """Get used disk space."""
    partitions = psutil.disk_partitions(False)
    for partition in partitions:
        usage = psutil.disk_usage(partition.mountpoint)
        if "/loop" in partition.device:
            continue
        # 10 ** 6 - convert between bytes to MB
        free_space_in_MB = usage.free / (10**6)
        # Do you have enough space?
        if free_space_in_MB > X:
            if free_space_in_MB > Z * Y:
                run_in_parallel(Z, Y, partition.mountpoint)
            else:
                print(f"You don't have eonugh space {Y*Z}MB in order to create {Z} file of size {Y}")
        else:
            print(f"You don't have more than {X}MB space in {partition.mountpoint}")

def main():
    arguments = parse_args()
    run_on_partition(arguments.free_space, arguments.number_of_files, arguments.size)
    print(f"----- {time.time() - start_time:.2f} seconds -----" )

if __name__ == "__main__":
    main()


import discord
from discord import app_commands
from discord.ext import commands
from utils.constants import owner_list
from typing import Optional, Literal

class OwnerCommands(commands.Cog):

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

    @commands.command()
    @commands.guild_only()
    @commands.is_owner()
    async def sync(self, ctx: commands.Context, guilds: commands.Greedy[discord.Object], spec: Optional[Literal["~", "*", "^"]] = None) -> None:
        if not guilds:
            if spec == "~":
                synced = await ctx.bot.tree.sync(guild=ctx.guild)
            elif spec == "*":
                ctx.bot.tree.copy_global_to(guild=ctx.guild)
                synced = await ctx.bot.tree.sync(guild=ctx.guild)
            elif spec == "^":
                ctx.bot.tree.clear_commands(guild=ctx.guild)
                await ctx.bot.tree.sync(guild=ctx.guild)
                synced = []
            else:
                synced = await ctx.bot.tree.sync()

            await ctx.send(
                f"Synced {len(synced)} commands {'globally' if spec is None else 'to the current guild.'}"
            )
            return

        ret = 0
        for guild in guilds:
            try:
                await ctx.bot.tree.sync(guild=guild)
            except discord.HTTPException:
                pass
            else:
                ret += 1

        await ctx.send(f"Synced the tree to {ret}/{len(guilds)}.")

    #Command which Loads a Module. Remember to use dot path. e.g: cogs.owner
    @commands.command(name='load')
    @commands.is_owner()
    async def load_cog(self, ctx: commands.Context, *, cog: str):
        try:
            await self.bot.load_extension(cog)
        except Exception as e:
            await ctx.send(f'**`ERROR:`** {type(e).__name__} - {e}')
        else:
            await ctx.send('**`SUCCESS`**')

    #Command which Unloads a Module. Remember to use dot path. e.g: cogs.owner
    @commands.command(name='unload')
    @commands.is_owner()
    async def unload_cog(self, ctx: commands.Context, *, cog: str):
        try:
            await self.bot.unload_extension(cog)
        except Exception as e:
            await ctx.send(f'**`ERROR:`** {type(e).__name__} - {e}')
        else:
            await ctx.send('**`SUCCESS`**')

    #Command which Reloads a Module. Remember to use dot path. e.g: cogs.owner
    @commands.command(name='reload')
    @commands.is_owner()
    async def reload_cog(self, ctx: commands.Context, *, cog: str):
        try:
            await self.bot.unload_extension(cog)
            await self.bot.load_extension(cog)
        except Exception as e:
            await ctx.send(f'**`ERROR:`** {type(e).__name__} - {e}')
        else:
            await ctx.send('**`SUCCESS`**')

# sync the owner_commands only in the BotTest Server
async def setup(bot: commands.Bot) -> None:
    await bot.add_cog(
        OwnerCommands(bot),
        guild = discord.Object(id=695553825494532127))


import os
import random

image_formats = ["PNG", "JPEG", "WEBP", "TIFF", "AVIF"]
image_header_size = [1280, 720]

image_width_height = [[640, 360], [320, 180], [320, 180], [300, 225], [300, 225], [240, 180], [240, 180],
                      [240, 180], [150, 150], [150, 150], [200, 200], [225, 300], [180, 240]]  # [width, height]
image_footer_logo_sizes = [[1, 1], [32, 32], [64, 64]]

def randomize_images(image_format):
    os.system("rm assets/images/*")
    with open("template.html", "r") as file:
        data = file.read()
        random.shuffle(image_width_height)
        random.shuffle(image_footer_logo_sizes)
        image_counter = 1

        # Header
        data = replace_tag_with_image_tag(image_header_size, data, image_counter, image_format)
        image_counter += 1

        # Body
        for size in image_width_height:
            data = replace_tag_with_image_tag(size, data, image_counter,image_format)
            image_counter += 1

        # Footer
        for size in image_footer_logo_sizes:
            data = replace_tag_with_image_tag(size, data, image_counter,image_format)
            image_counter += 1

    with open("index.html", "w") as file:
        file.write(data)

def replace_tag_with_image_tag(size, data, image_number, image_format):
    image_to_replace = f"<!-- Image {image_number} -->"
    random_image_selected = select_random_image(size[0], size[1])
    random_image_selected_with_format = random_image_selected + image_format.lower()
    replace_text = create_image_file_tag(size[0], size[1], random_image_selected_with_format, "A short descrition of the image")
    data = data.replace(image_to_replace, replace_text)
    return data

def select_random_image(width, height):
    random_int = random.randint(1, 625)
    image_name = f"image_{random_int}_{width}x{height}."
    for image_format in image_formats:
        image_name_with_format = image_name + image_format.lower()
        os.system(f"cp converted/{image_name_with_format} assets/images/{image_name_with_format}")
    return image_name

def create_image_file_tag(width, height, image_name, alt_text):
    image_file_tag = f'<img src="/assets/images/{image_name}" alt="{alt_text}" width="{width}" height="{height}">'
    return image_file_tag

def change_current_format_file(standard_image_format):
    file_image_format= open("current_format.txt", "w")
    file_image_format.write(standard_image_format)
    file_image_format.close()

if __name__ == '__main__':
    standard_image_format = "png"
    randomize_images(standard_image_format)
    change_current_format_file(standard_image_format)
    print("Done")


import argparse
import re

def read_towers(f):
    towers = []
    for line in f:
        if line == "\n":
            break
        items = [line[i : i + 4].strip() for i in range(0, len(line), 4)]
        if not towers:
            for i in range(len(items)):
                towers.append([])
        if any(item.isnumeric() for item in items):
            break
        for idx, item in enumerate(items):
            if item:
                towers[idx].append(item.replace("[", "").replace("]", ""))
    for tower in towers:
        tower.reverse()
    towers.insert(0, None)  # 1-indexed
    return towers

def main(args):
    with open(args.file, "r") as f:
        towers = read_towers(f)
        assert f.readline() == "\n"
        for command in f:
            groups = re.match(r"move (\d+) from (\d+) to (\d+)", command).groups()
            count, from_, to = map(int, groups)
            to_move = towers[from_][-count:]
            del towers[from_][-count:]
            towers[to].extend(to_move)
    return "".join(tower[-1] for tower in towers[1:])

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--file", default="/dev/stdin")
    args = parser.parse_args()
    print(main(args))


"""
# 405
Easy
Convert a Number to Hexadecimal

https://leetcode.com/problems/convert-a-number-to-hexadecimal/

Given an integer num, return a string representing its hexadecimal representation.
For negative integers, two's complement method is used.

All the letters in the answer string should be lowercase characters, and there should not be any leading zeros in the answer except for the zero itself.

Note: You are not allowed to use any built-in library method to directly solve this problem.

Example 1:
Input: num = 26
Output: "1a"

Example 2:
Input: num = -1
Output: "ffffffff"

Constraints:
-2^31 <= num <= 2^31 - 1
"""

def to_hex(num: int) -> str:
    if num == 0:
        return "0"

    alph = "0123456789abcdef"

    if num < 0:
        num = 2**32 + num

    result = ""

    while num > 0:
        result = alph[num % 16] + result

        num //= 16

    return result

if __name__ == "__main__":
    assert to_hex(26) == "1a"
    assert to_hex(-1) == "ffffffff"


def check():
    for i in range(1, n+1):
        x = (pd * i) / 100
        y = (pd * i) // 100
        if x == y:
            return "Possible"
    return "Broken"

t = int(input())
for idx in range(1, t+1):
    n, pd, pg = map(int, input().split())

    result = "Possible"
    if pg == 100 and pd != 100:
        result = "Broken"
    elif pg == 0 and pd != 0:
        result = "Broken"
    else:
        result = check()

    print("#{} {}".format(idx, result))


import io
import tempfile
import pathlib
from urllib.parse import urlparse, urlunparse
from html.parser import HTMLParser

from .processor import BaseProcessor

class LinkParser(HTMLParser):
    def __init__(self):
        super().__init__()
        self.reference_paths = []

    def handle_starttag(self, tag, attrs):
        super().handle_starttag(tag, attrs)

        for attr in attrs:
            (tag, value) = attr
            if tag in ['href', 'src', 'src']:
                parse_result = urlparse(value)
                self.reference_paths.append(parse_result)

class HTMLHandler(BaseProcessor):
    """
    """
    def __init__(self, logger, watch_path):
        self.logger = logger.getChild("HTMLHandler")
        self.watch_path = watch_path

    def link_within_watchdir(self, abs_item_path):
        try:
            abs_item_path.relative_to(self.watch_path)
            return True
        except ValueError:
            return False

    def process_file(self, file_stream, orig_file_path, type_result):
        (content_type, _) = type_result
        if not content_type or "html" not in content_type:
            self.logger.debug("Skipping non-HTML data")
            return (file_stream, None, None)

        # Wrap file stream into text stream.
        reader = io.BufferedReader(file_stream)
        wrapper = io.TextIOWrapper(reader)

        # Build temporary file which contains replaced data
        # temp_file = tempfile.TemporaryFile('w+b')

        # Reset all streams before operations
        wrapper.seek(0)

        # Parse all links from the html
        parser = LinkParser()
        next_line = wrapper.readline()
        while next_line: # String is not empty
            parser.feed(next_line)
            next_line = wrapper.readline()

        # Process all links relative to the original path
        links = parser.reference_paths
        original_containing_path = orig_file_path.parent
        referenced_items = []
        for link in links:
            self.logger.debug("Found link `%s`", urlunparse(link))
            self.logger.debug("%s", link)
            if not link.scheme or link.scheme == "file":
                path_str = link.path.strip().lstrip('/')
                path = pathlib.Path(path_str)
                if not path.is_absolute():
                    path = pathlib.Path(original_containing_path, path)

                if not path.exists():
                    self.logger.warn("No resource found at referenced location `%s`!", path.as_posix())
                    continue

                # Path MUST be an absolute version!
                if not self.link_within_watchdir(path):
                    warn_str = "Link outside watchdir: `%s` \nMove the resource inside the watchdir!"
                    self.logger.warn(warn_str, path.as_posix())
                    continue

                # Store the path object as a referenced item which must be uploaded as well.
                referenced_items.append(path)

        # Make sure the stream is not closed after destruction of the reader
        reader.detach()
        # Reset stream to initial position
        file_stream.seek(0)
        return (file_stream, None, referenced_items)


"""
1.数据列表页面，定制显示列
    # your admin.py
    from maya.service import admin
    from [app_name] import [Model]

    示例一: 显示对象列表

        admin.site.register(Model)

    示例二: 个性化定制

        class SubClass(admin.MayaAdmin)

            def func(self,model_obj=None,is_header=False)
                if is_header:
                    return "header_name"
                else:
                    return "%s-%s"%(model_obj.username,model_obj.password)

            list_display = [func,string...]

        admin.site.register(Model,SubClass)
        PS:字段可以
            - 字符串 (数据库列名)
            - 函数

    完整示例：
        # from maya.service import admin
        # from django.urls import reverse
        # from django.utils.safestring import mark_safe
        # from app01 import models
        #
        # class UserInfoAdmin(admin.MayaAdmin):
        #
        #     def option(self,model_obj=None,is_header=False):
        #         if is_header:
        #             return "操作"
        #         else:
        #             # reverse url
        #             edit_url = reverse("{0}:{1}_{2}_change".format(
        #                     self.site.namespace,
        #                     self.model_class._meta.app_label,
        #                     self.model_class._meta.model_name
        #                 ),
        #                 args=(model_obj.pk,)
        #             )
        #             del_url = reverse("{0}:{1}_{2}_delete".format(
        #                 self.site.namespace,
        #                 self.model_class._meta.app_label,
        #                 self.model_class._meta.model_name
        #             ),
        #                 args=(model_obj.pk,)
        #             )
        #
        #             return mark_safe("编辑 | 删除 | 详细".format(edit_url,del_url))
        #
        #     def checkbox(self,model_obj=None,is_header=False):
        #         if is_header:
        #             return mark_safe(
        #                 "<input type='button' value='全选'><input type='button' value='反选'><input type='button' value='取消'>")
        #         else:
        #             return mark_safe("<input type='checkbox' value='{0}'>".format(model_obj.pk))
        #
        #
        #    list_display = (checkbox,'id','username','password',option)

"""
from django.conf.urls import url,include
from django.shortcuts import HttpResponse,render,redirect
from django.http.request import QueryDict
from django.urls import reverse
import json

class MayaAdmin(object):

    #默认显示列
    list_display = "__all__"

    #默认action
    list_action = []

    #搜索
    list_filter = []

    add_edit_model_from = None

    def __init__(self,model_class,site):
        self.model_class = model_class
        self.site = site
        self.request = None
        self.app_label = self.model_class._meta.app_label
        self.model_name = self.model_class._meta.model_name

    @property
    def urls(self):
        info = self.app_label,self.model_name
        urlpatterns = [
            url(r'^$', self.changelist_view, name='%s_%s_changelist' % info),
            url(r'^add/$', self.add_view, name='%s_%s_add' % info),
            url(r'^(.+)/delete/$', self.delete_view, name='%s_%s_delete' % info),
            url(r'^(.+)/change/$', self.change_view, name='%s_%s_change' % info),
        ]
        return urlpatterns

    def get_add_edit_model_form(self):
        if self.add_edit_model_from:
            return self.add_edit_model_from
        else:
            from django.forms import ModelForm

            # class AddModelForm(ModelForm):
            #     class Meta:
            #         model = self.model_class
            #         fields = "__all__"

            _meta = type('Meta',(object,),{"model":self.model_class,"fields":"__all__"})
            DefaultForm = type('DefaultModelForm',(ModelForm,),{"Meta":_meta})

            return DefaultForm

    def changelist_view(self,request):
        """
        查询数据
        """

        self.request = request

        param_dict = QueryDict(mutable=True)

        #获取get参数
        if request.GET:
            param_dict['change_list_filter'] = request.GET.urlencode()

        #添加按钮URL生成
        base_add_url = reverse("{0}:{1}_{2}_add".format(self.site.namespace,self.app_label,self.model_name))
        add_url = "{0}?{1}".format(base_add_url,param_dict.urlencode())

        """
        分页功能
        """
        from maya.utils import pagination
        from copy import deepcopy

        condition = {}
        print(request.GET)

        page_param_dict = deepcopy(request.GET)
        page_param_dict._mutable = True

        prefix_url = reverse("{0}:{1}_{2}_changelist".format(self.site.namespace,self.app_label,self.model_name))
        total_num = self.model_class.objects.filter(**condition).count()
        page_info = pagination.PageInfo(request.GET.get('page'),total_num,prefix_url,page_param_dict,2,10,)

        """
        Action
        """
        action_list = []
        for action in self.list_action:
            action_list.append({
                'name':action.__name__,
                'text':action.text
            })

        if request.method == "POST":
            action_func = request.POST.get('action')
            ret = getattr(self,action_func)(request)
            base_url = reverse("{0}:{1}_{2}_changelist".format(self.site.namespace, self.app_label,self.model_name))
            if ret:
                base_url = "{0}?{1}".format(base_url,request.GET.urlencode())

            return redirect(base_url)

        """
        组合搜索
        """
        from django.db.models import ManyToManyField,ForeignKey
        from maya.utils.filter import FilterList
        def get_list_filter():
            for option in self.list_filter:
                if option.is_func:
                    filter_data = option.field_or_func(self,option,request)
                else:
                    field = self.model_class._meta.get_field(option.field_or_func)
                    if isinstance(field,ForeignKey):
                        filter_data = FilterList(option,field.rel.model.objects.all(),request)
                    elif isinstance(field,ManyToManyField):
                        filter_data = FilterList(option,field.rel.model.objects.all(),request)
                    else:
                        filter_data = FilterList(option, field.model.objects.all(),request)

                yield filter_data

        context ={
            'data_list':self.model_class.objects.all(**condition)[page_info.start:page_info.end],
            'list_display':self.list_display,
            'maya_admin':self,
            'add_url':add_url,
            'page_index':page_info.page_index,
            'action_list':action_list,
            'filter_data_list':get_list_filter()
        }

        return render(request,'change_list.html',context)

    def add_view(self,request):
        """
        添加数据
        """

        if request.method == "GET":
            AddModelForm = self.get_add_edit_model_form()()

        else:
            AddModelForm = self.get_add_edit_model_form()(data=request.POST,files=request.FILES)
            if AddModelForm.is_valid():
                obj = AddModelForm.save()

                popup_id = request.GET.get('popup')
                #popup请求跳转
                if popup_id:

                    context={
                        'popup_dict':json.dumps({'popup_id':popup_id,'content':str(obj),'id':obj.pk,})
                    }

                    return render(request, 'popup_response.html',context)

                # 添加成功中转回list页面
                base_list_url = reverse("{0}:{1}_{2}_changelist".format(
                    self.site.namespace,
                    self.model_class._meta.app_label,
                    self.model_class._meta.model_name)
                )
                list_url = "{0}?{1}".format(base_list_url, request.GET.get('change_list_filter'))

                return redirect(list_url)

        context = {
            'form':AddModelForm,
            'maya_admin':self,
        }

        return render(request,'add.html',context)

    def delete_view(self,request,pk):
        """
        删除数据
        :param pk: 数据行主键id
        """
        info = self.model_class._meta.app_label, self.model_class._meta.model_name
        return HttpResponse('%s_%s_delete'%info)

    def change_view(self,request,pk):
        """
        修改数据
        :param object_id:数据行id
        """
        obj = self.model_class.objects.filter(pk=pk).first()

        if request.method == "GET":
            EditModelForm = self.get_add_edit_model_form()(instance=obj)
        else:
            EditModelForm = self.get_add_edit_model_form()(data=request.POST,files=request.FILES,instance=obj)
            if EditModelForm.is_valid():
                EditModelForm.save()

                # 添加成功中转回list页面
                base_list_url = reverse("{0}:{1}_{2}_changelist".format(
                    self.site.namespace,
                    self.model_class._meta.app_label,
                    self.model_class._meta.model_name)
                )
                list_url = "{0}?{1}".format(base_list_url, request.GET.get('change_list_filter'))

                return redirect(list_url)

        context = {
            'form':EditModelForm
        }

        return render(request,'edit.html',context)

class MayaSite(object):

    def __init__(self):
        self._registry = {}
        self.namespace = 'maya'
        self.app_name = 'maya'

    def register(self,model_class,MayaAdmin=MayaAdmin):
        self._registry[model_class] = MayaAdmin(model_class,self)

    def get_urls(self):
        urlpatterns = []

        for model_cls,maya_admin_obj in self._registry.items():
            app_label = model_cls._meta.app_label
            model_name = model_cls._meta.model_name
            urlpatterns.append(url(r'^%s/%s/'%(app_label,model_name), include(maya_admin_obj.urls)))

        return urlpatterns

    @property
    def urls(self):
        return self.get_urls(),self.app_name,self.namespace

site = MayaSite()


import math
import open3d
import numpy as np
import torch
import pytorch3d.loss
import pytorch3d.ops
import pytorch3d.structures
from pytorch3d.loss.point_mesh_distance import point_face_distance
from torch_cluster import fps
from loss.emd.emd_module import emdFunction
from models.net_utils import normalize_sphere, normalize_pcl

def chamfer_distance_unit_sphere(gen, ref, batch_reduction='mean', point_reduction='mean'):
    # ref, center, scale = normalize_sphere(ref)
    # gen = normalize_pcl(gen, center, scale)
    return pytorch3d.loss.chamfer_distance(gen, ref, batch_reduction=batch_reduction, point_reduction=point_reduction)

def get_repulsion_loss(pred, k=4, eps=1e-12, h=0.03, radius=0.07):
    _, idx, grouped_points = pytorch3d.ops.knn_points(pred, pred, K=k, return_nn=True) ## idx:(B, N, K); grouped_points(B,N,K,3)
    # idx = idx[:, :, 1:].to(torch.int32) # remove first one
    # idx = idx.contiguous() # B, N, nn
    #
    pred = pred.permute(0, 2, 1).contiguous() # B, 3, N
    grouped_points = grouped_points.permute(0, 3, 1, 2).contiguous()  # B, 3, N, K
    # grouped_points = pytorch3d.ops.knn_gather(pred, idx) # (B, 3, N), (B, N, nn) => (B, 3, N, nn)

    grouped_points = grouped_points - pred.unsqueeze(-1)
    dist2 = torch.sum(grouped_points ** 2, dim=1)
    dist2 = torch.max(dist2, torch.tensor(eps).cuda())
    dist = torch.sqrt(dist2)
    weight = torch.exp(- dist2 / h ** 2)

    uniform_loss = torch.mean((torch.tensor(radius).cuda() - dist) * weight)
    # uniform_loss = torch.mean(self.radius - dist * weight) # punet
    # print("uniform_loss", uniform_loss, uniform_loss.shape)
    return uniform_loss

# def point_to_mesh_distance_single_unit_sphere(pcl, verts, faces):
#     """
#     Args:
#         pcl:    (N, 3).
#         verts:  (M, 3).
#         faces:  LongTensor, (T, 3).
#     Returns:
#         Squared pointwise distances, (N, ).
#     """

#     assert pcl.dim() == 2 and verts.dim() == 2 and faces.dim() == 2, 'Batch is not supported.'

#     # Normalize mesh
#     verts, center, scale = normalize_sphere(verts.unsqueeze(0))
#     verts = verts[0]
#     # Normalize pcl
#     pcl = normalize_pcl(pcl.unsqueeze(0), center=center, scale=scale)
#     pcl = pcl[0]

#     # print('%.6f %.6f' % (verts.abs().max().item(), pcl.abs().max().item()))

#     # Convert them to pytorch3d structures
#     pcls = pytorch3d.structures.Pointclouds([pcl])
#     meshes = pytorch3d.structures.Meshes([verts], [faces])

#     N = len(meshes)

#     # packed representation for pointclouds
#     points = pcls.points_packed()  # (P, 3)
#     points_first_idx = pcls.cloud_to_packed_first_idx()
#     max_points = pcls.num_points_per_cloud().max().item()

#     # packed representation for faces
#     verts_packed = meshes.verts_packed()
#     faces_packed = meshes.faces_packed()
#     tris = verts_packed[faces_packed]  # (T, 3, 3)
#     tris_first_idx = meshes.mesh_to_faces_packed_first_idx()
#     max_tris = meshes.num_faces_per_mesh().max().item()

#     # point to face distance: shape (P,)
#     point_to_face = point_face_distance(
#         points, points_first_idx, tris, tris_first_idx, max_points
#     )

#     return point_to_face

def Point2Face_distance(meshes, pcls):
    """
    Computes the distance between a pointcloud and a mesh within a batch.
    Given a pair `(mesh, pcl)` in the batch, we define the distance to be the
    sum of two distances, namely `point_face(mesh, pcl) + face_point(mesh, pcl)`

    `point_face(mesh, pcl)`: Computes the squared distance of each point p in pcl
        to the closest triangular face in mesh and averages across all points in pcl
    `face_point(mesh, pcl)`: Computes the squared distance of each triangular face in
        mesh to the closest point in pcl and averages across all faces in mesh.

    The above distance functions are applied for all `(mesh, pcl)` pairs in the batch
    and then averaged across the batch.

    Args:
        meshes: A Meshes data structure containing N meshes
        pcls: A Pointclouds data structure containing N pointclouds

    Returns:
        loss: The `point_face(mesh, pcl)` distance
            between all `(mesh, pcl)` in a batch averaged across the batch.
    """

    if len(meshes) != len(pcls):
        raise ValueError("meshes and pointclouds must be equal sized batches")
    N = len(meshes)

    # packed representation for pointclouds
    points = pcls.points_packed()  # (P, 3)
    points_first_idx = pcls.cloud_to_packed_first_idx()
    max_points = pcls.num_points_per_cloud().max().item()

    # packed representation for faces
    verts_packed = meshes.verts_packed()
    faces_packed = meshes.faces_packed()
    tris = verts_packed[faces_packed]  # (T, 3, 3)
    tris_first_idx = meshes.mesh_to_faces_packed_first_idx()
    max_tris = meshes.num_faces_per_mesh().max().item()

    # point to face distance: shape (P,)
    point_to_face = point_face_distance(
        points, points_first_idx, tris, tris_first_idx, max_points
    )

    point_to_face = torch.sqrt(point_to_face).mean(0)

    return point_to_face

def point_mesh_bidir_distance_single_unit_sphere(pcl, verts, faces):
    """
    Args:
        pcl:    (N, 3).
        verts:  (M, 3).
        faces:  LongTensor, (T, 3).
    Returns:
        Squared pointwise distances, (N, ).
    """
    assert pcl.dim() == 2 and verts.dim() == 2 and faces.dim() == 2, 'Batch is not supported.'

    # Normalize mesh
    verts, center, scale = normalize_sphere(verts.unsqueeze(0))
    verts = verts[0]
    # Normalize pcl
    pcl = normalize_pcl(pcl.unsqueeze(0), center=center, scale=scale)
    pcl = pcl[0]

    # print('%.6f %.6f' % (verts.abs().max().item(), pcl.abs().max().item()))

    # Convert them to pytorch3d structures
    pcls = pytorch3d.structures.Pointclouds([pcl])
    meshes = pytorch3d.structures.Meshes([verts], [faces])
    return pytorch3d.loss.point_mesh_face_distance(meshes, pcls)
    # return Point2Face_distance(meshes, pcls)

def hausdorff_distance_unit_sphere(gen, ref):
    """
    Args:
        gen:    (B, N, 3)
        ref:    (B, N, 3)
    Returns:
        (B, )
    """
    # ref, center, scale = normalize_sphere(ref)
    # gen = normalize_pcl(gen, center, scale)

    dists_ab, _, _ = pytorch3d.ops.knn_points(ref, gen, K=1)
    dists_ab = dists_ab[:,:,0].max(dim=1, keepdim=True)[0]  # (B, 1)
    # print(dists_ab)

    dists_ba, _, _ = pytorch3d.ops.knn_points(gen, ref, K=1)
    dists_ba = dists_ba[:,:,0].max(dim=1, keepdim=True)[0]  # (B, 1)
    # print(dists_ba)

    dists_hausdorff = torch.max(torch.cat([dists_ab, dists_ba], dim=1), dim=1)[0]

    return dists_hausdorff

def emd_loss(preds, gts, eps=0.005, iters=100):
    loss, assignment = emdFunction.apply(preds, gts, eps, iters)
    return loss, assignment

def get_knn_idx_dist(pos:torch.FloatTensor, query:torch.FloatTensor, k, offset=0):
    """
    :param  pos:     (B, N, F)
    :param  query:   (B, M, F)
    :return knn_idx: (B, M, k)
    """
    B, N, F = tuple(pos.size())
    M = query.size(1)

    pos = pos.unsqueeze(1).expand(B, M, N, F)
    query = query.unsqueeze(2).expand(B, M, N, F)   # B * M * N * F
    dist = torch.sum((pos - query) ** 2, dim=3, keepdim=False)   # B * M * N
    knn_idx = torch.argsort(dist, dim=2)[:, :, offset:k+offset]   # B * M * k
    knn_dist = torch.gather(dist, dim=2, index=knn_idx)           # B * M * k

    return knn_idx, knn_dist

def RepulsionLoss(pc, knn=4, h=0.03):

    knn_idx, knn_dist = get_knn_idx_dist(pc, pc, k=knn, offset=1)  # (B, N, k)
    weight = torch.exp(- knn_dist / (h ** 2))
    loss = torch.sum(- knn_dist * weight)
    return loss

def point_density(pcl, knn):
    """

    Args:
        pcl: B,N,3

    Returns:
        point-wise density: B, N, 1

    """
    knn_dst, knn_idx, _ = pytorch3d.ops.knn_points(pcl, pcl, K=knn, return_nn=True)  # [B N K]
    # knn_dst_max = torch.max(knn_dst, dim=-1, keepdim=True)[0]   # [B N 1]
    density = knn_dst[:,:,1:].mean(-1, keepdim=True)  # [B N 1]
    return density

def patch_density(pcl_low, pcl_high, pcl_up, knn):
    """

    pc_low: B,N,3
        pcl_high: B,R*N,3
        pcl_up: B,R*N,3
        knn: the nearest points
    Returns:
        loss

    """
    knn_dst_h, knn_idx_h, _ = pytorch3d.ops.knn_points(pcl_low, pcl_high, K=knn, return_nn=True)  # [B N K]
    knn_dst_up, knn_idx_up, _ = pytorch3d.ops.knn_points(pcl_low, pcl_up, K=knn, return_nn=True)  # [B N K]
    # weight = torch.exp(torch.abs(knn_dst_h.mean(dim=-1) - knn_dst_up.mean(dim=-1))) #2022.4.12
    # weight = torch.abs(knn_dst_h.mean(dim=-1) - knn_dst_up.mean(dim=-1))  #2022-4-14
    dst_h_mean = knn_dst_h[:,:,1:].mean(dim=-1, keepdim=True)
    dst_up_mean = knn_dst_up[:,:,1:].mean(dim=-1, keepdim=True)
    # density1 = torch.sum(torch.abs(dst_h_mean - dst_up_mean) + (knn_dst_h - dst_h_mean) ** 2 + (knn_dst_up - dst_up_mean) ** 2)
    density = torch.abs(dst_h_mean - dst_up_mean).mean() + torch.abs((knn_dst_h - dst_h_mean) ** 2 - (knn_dst_up - dst_up_mean) ** 2).mean()
    return density, knn_idx_h, knn_idx_up

# 2022-4-21
# def DensityLoss(pcl_low, pcl_high, pcl_up, knn=4, alpha=100):
#     """
#     Args:
#         pc_low: B,N,3
#         pcl_high: B,R*N,3
#         pcl_up: B,R*N,3
#         knn: the nearest points
#     Returns:
#         loss
#     """
#     pcl_low = pcl_low[:, :, :3]
#     pcl_high = pcl_high[:, :, :3]
#     pcl_up = pcl_up[:, :, :3]
#     B, N, _ = pcl_low.shape
#     pcl_up_density = point_density(pcl_up, knn) # [B N 1]
#     pcl_high_density = point_density(pcl_high, knn) # [B N 1]
#     patch_dense, knn_idx_h, knn_idx_up = patch_density(pcl_low, pcl_high, pcl_up, knn)
#     up_density_knn = pytorch3d.ops.knn_gather(pcl_up_density, knn_idx_up)
#     high_density_knn = pytorch3d.ops.knn_gather(pcl_high_density, knn_idx_h)
#     point_dense = torch.abs(up_density_knn - high_density_knn).mean()
#     density = patch_dense + point_dense
#     return density

# def DensityLoss(pcl_low, pcl_high, pcl_up, knn=4, alpha=100):
#     """
#     Args:
#         pc_low: B,N,3
#         pcl_high: B,R*N,3
#         pcl_up: B,R*N,3
#         knn: the nearest points
#     Returns:
#         loss
#     """
#     pcl_low = pcl_low[:, :, :3] # B,N,3
#     pcl_high = pcl_high[:, :, :3] # B,RN,3
#     pcl_up = pcl_up[:, :, :3] # B,RN,3
#     B, N, _ = pcl_low.shape
#     _, knn_idx_low, knn_low = pytorch3d.ops.knn_points(pcl_low, pcl_low, K=int(knn/3), return_nn=True)  # [B N K]
#     _, knn_idx_up, knn_up = pytorch3d.ops.knn_points(knn_low.reshape(B, -1, 3), pcl_up, K=knn, return_nn=True)  # [B N K]
#     _, knn_idx_high, knn_high = pytorch3d.ops.knn_points(knn_low.reshape(B, -1, 3), pcl_high, K=knn, return_nn=True)  # [B N K]
#     knn_up = knn_up.reshape(B, N, -1, 3)
#     knn_high = knn_high.reshape(B, N, -1, 3)
#     dst_low_up = (knn_up - pcl_low.unsqueeze(-2)).norm(p=2,dim=-1)
#     dst_low_high = (knn_high - pcl_low.unsqueeze(-2)).norm(p=2,dim=-1)
#     density = torch.abs(dst_low_up - dst_low_high).sum(dim=-1).mean()
#     return density

# def DensityLoss(pcl_low, pcl_high, knn=4, alpha=1000):
#     """
#     Args:
#         pc_low: B,N,3
#         pcl_high: B,R*N,3
#         pcl_up: B,R*N,3
#         knn: the nearest points
#     Returns:
#         loss
#     """
#     pcl_low = pcl_low[:, :, :3]
#     pcl_high = pcl_high[:, :, :3]
#     B, N, _ = pcl_low.shape
#     knn_dst_h, knn_idx_h, knn_point = pytorch3d.ops.knn_points(pcl_low, pcl_high, K=knn, return_nn=True)  # [B N K]
#     # weight = torch.exp( - alpha * torch.norm(knn_point - pcl_low.unsqueeze(-2).repeat(1,1,knn,1), p=2, dim=-1, keepdim=True))
#     weight = torch.exp(- alpha * knn_dst_h)
#     # weight = weight / (weight.sum(-1, keepdim=True) + 1e-7)
#     proj_point = torch.matmul(weight.unsqueeze(-1).permute(0,1,3,2), knn_point).squeeze(-2) / (weight.sum(-1, keepdim=True) + 1e-7)
#     density = torch.norm(pcl_low - proj_point, p=2, dim=-1).mean(-1)
#     return density.mean()

def square_distance(src, dst):
    B, N, _ = src.shape
    _, M, _ = dst.shape
    dist = -2 * torch.matmul(src, dst.permute(0, 2, 1))
    dist += torch.sum(src ** 2, -1).view(B, N, 1)
    dist += torch.sum(dst ** 2, -1).view(B, 1, M)
    return dist

def DensityLoss(pcl_high, pcl_up, knn=4, t=0.01, alpha=100):
    """
    Args:
        pcl_high: B,R*N,3
        pcl_up: B,R*N,3
        knn: the nearest points
    Returns:
        loss
    """
    pcl_high = pcl_high[:, :, :3] # B,RN,3
    pcl_up = pcl_up[:, :, :3] # B,RN,3
    B, N, C = pcl_up.shape
    B, M, _ = pcl_high.shape
    knn_high_up_dst, knn_idx_high_up, knn_high_up = pytorch3d.ops.knn_points(pcl_high, pcl_up, K=knn, return_nn=True)  # [B N K]
    knn_high_high_dst, knn_idx_high_high, knn_high_high = pytorch3d.ops.knn_points(pcl_high, pcl_high, K=knn, return_nn=True)  # [B N K]
    # weight_high_up = torch.exp( -knn_high_up_dst / t ).unsqueeze(-1).repeat(1,1,1,C)
    # weight_high_high = torch.exp( -knn_high_high_dst / t ).unsqueeze(-1).repeat(1,1,1,C)
    # mean_knn_high_up = torch.mul(knn_high_up, weight_high_up).mean(-2)
    # mean_knn_up_high = torch.mul(knn_high_high, weight_high_high).mean(-2)
    mean_point = torch.abs(knn_high_up.mean(-2) - knn_high_high.mean(-2)).sum(-1).mean()
    # mean_dst = (torch.abs(knn_high_up_dst.sum(-1)-knn_high_high_dst.sum(-1)) ** 2).mean()
    knn_high_up = knn_high_up.reshape(B*N, knn, C)
    knn_high_high = knn_high_high.reshape(B * N, knn, C)
    mean_dst = torch.abs(square_distance(knn_high_high, knn_high_high).sum(-1).sum(-1) - square_distance(knn_high_up, knn_high_up).sum(-1).sum(-1)).mean()
    density = mean_point + mean_dst   #2022_08_08__11_32_57
    ###xinzeng/2022_08_08__23_28_50
    # loss_dst = torch.abs(knn_high_high_dst - knn_high_up_dst).mean()
    # density = mean_point + mean_dst + loss_dst
    # density = mean_dst
    return density

def get_normal_vector(points):
    B, N, _ = points.shape
    pcd = open3d.geometry.PointCloud()
    pcd.points = open3d.utility.Vector3dVector(points.reshape(-1, 3).detach().cpu().numpy())
    pcd.estimate_normals(search_param=open3d.geometry.KDTreeSearchParamKNN(knn=4))
    normal_vec = torch.FloatTensor(pcd.normals).cuda().reshape(B, N, -1)
    return normal_vec

def NormalLoss(pcl_low, pcl_high, pcl_up, knn=4):
    """
    Args:
        pc_low: B,N,3
        pcl_high: B,R*N,3
        pcl_up: B,R*N,3
        knn: the nearest points
    Returns:
        loss
    """
    pcl_low = pcl_low[:, :, :3]  # [B N K]
    pcl_high = pcl_high[:, :, :3]  # [B R*N K]
    pcl_up = pcl_up[:, :, :3]  # [B R*N K]
    nor_high = get_normal_vector(pcl_high)  # [B R*N 3]
    nor_up = get_normal_vector(pcl_up)  # [B R*N 3]
    # nor_up_knn = pytorch3d.ops.knn_gather(nor_up, knn_idx_h)
    _, knn_idx_h, _ = pytorch3d.ops.knn_points(pcl_low, pcl_high, K=knn, return_nn=True)  # [B N K]
    _, knn_idx_up, _ = pytorch3d.ops.knn_points(pcl_low, pcl_up, K=knn, return_nn=True)  # [B N K]
    nor_high_knn = pytorch3d.ops.knn_gather(nor_high, knn_idx_h)  # [B N K 3]
    nor_up_knn = pytorch3d.ops.knn_gather(nor_up, knn_idx_up)  # [B N K 3]
    nor_0 = torch.sum((nor_high_knn - nor_up_knn) ** 2, dim=-1)  # [B N K]
    nor_1 = torch.sum((nor_high_knn + nor_up_knn) ** 2, dim=-1)  # [B N K]
    normal = torch.max(nor_0, nor_1)
    return torch.sum(normal)

def angle_point(pc1, pc2, k):
    """
    Args:
        pc1: B, N, 3
        pc2: B, N, 3
        k: KNN

    Returns:
        angle: the angle of each point, B, N
    """
    INNER_PRODUCT_THRESHOLD = math.pi / 2
    _, idx, pc1_knn = pytorch3d.ops.knn_points(pc1, pc2, K=k, return_nn=True)

    inner_prod = (pc1_knn * pc1.unsqueeze(-2)).sum(dim=-1)
    pc1_knn_norm = torch.norm(pc1_knn,p=2,dim=-1)
    pc1_norm = torch.norm(pc1.unsqueeze(-2).repeat(1,1,k,1), p=2, dim=-1)
    inner_prod = inner_prod / (pc1_knn_norm * pc1_norm)
    # inner_prod[inner_prod > 1] = 1
    # inner_prod[inner_prod < -1] = -1
    angle = torch.acos(inner_prod)
    # angle[angle > INNER_PRODUCT_THRESHOLD] = math.pi - angle[angle > INNER_PRODUCT_THRESHOLD]
    # angle = angle.sum(dim=-1)
    return angle

def density_point(pc1, pc2, knn, t):
    """
    Args:
        pc1: B, N, 3
        pc2: B, N, 3
        k: KNN

    Returns:
        angle: the angle of each point, B, N
    """
    B, N, C = pc1.shape
    _, M, _ = pc2.shape
    knn_dst, knn_idx, knn_point = pytorch3d.ops.knn_points(pc1, pc2, K=knn, return_nn=True)  # [B N K]
    weight = torch.exp(-knn_dst / t).unsqueeze(-1).repeat(1, 1, 1, C)
    mean_point = torch.mul(knn_point, weight).mean(-2)
    return mean_point

# def Density_Angle(pcl_high, pcl_up, knn=4, t=0.01, alpha=100):
#     """
#     Args:
#         pcl_high: B,R*N,3
#         pcl_up: B,R*N,3
#         knn: the nearest points
#     Returns:
#         loss
#     """
#     pcl_high = pcl_high[:, :, :3] # B,RN,3
#     pcl_up = pcl_up[:, :, :3] # B,RN,3
#     # knn_high_up_dst, knn_idx_high_up, knn_high_up = pytorch3d.ops.knn_points(pcl_high, pcl_up, K=knn, return_nn=True)  # [B N K]
#     # knn_high_high_dst, knn_idx_high_high, knn_high_high = pytorch3d.ops.knn_points(pcl_high, pcl_high, K=knn, return_nn=True)  # [B N K]
#     # weight_high_up = torch.exp( -knn_high_up_dst / t ).unsqueeze(-1).repeat(1,1,1,C)
#     # weight_high_high = torch.exp( -knn_high_high_dst / t ).unsqueeze(-1).repeat(1,1,1,C)
#     # mean_knn_high_up = torch.mul(knn_high_up, weight_high_up).mean(-2)
#     # mean_knn_high_high = torch.mul(knn_high_high, weight_high_high).mean(-2)
#     # mean_point = ((knn_high_up.mean(-2) - knn_high_high.mean(-2)) ** 2).sum(-1).mean()
#     mean_knn_high_high = density_point(pcl_high, pcl_high, knn, t)
#     mean_knn_high_up = density_point(pcl_high, pcl_up, knn, t)
#     # mean_point = (torch.abs(mean_knn_high_high - mean_knn_high_up)).sum(-1).mean()
#     mean_point = (torch.abs(mean_knn_high_up - pcl_high).sum(-1)).mean()
#     # mean_dst = (torch.abs(knn_high_up_dst.sum(-1)-knn_high_high_dst.sum(-1)) ** 2).mean()
#     angle_high_up = angle_point(pcl_high, pcl_high, knn)
#     angle_high_high = angle_point(pcl_high, pcl_up, knn)
#     loss_angle = torch.abs(angle_high_high - angle_high_up).mean()
#     loss = mean_point
#     return loss

def Density_Angle(pcl_high, pcl_up, knn=4):
    """
    Args:
        pcl_high: B,R*N,3
        pcl_up: B,R*N,3
        knn: the nearest points
    Returns:
        loss
    """
    pcl_high = pcl_high[:, :, :3] # B,RN,3
    pcl_up = pcl_up[:, :, :3] # B,RN,3
    knn_high_up_dst, knn_idx_high_up, knn_high_up = pytorch3d.ops.knn_points(pcl_high, pcl_up, K=knn, return_nn=True)  # [B N K]
    knn_high_high_dst, knn_idx_high_high, knn_high_high = pytorch3d.ops.knn_points(pcl_high, pcl_high, K=knn, return_nn=True)  # [B N K]
    vec_high_up = pcl_high.unsqueeze(-2) - knn_high_up
    vec_high_high = pcl_high.unsqueeze(-2) - knn_high_high
    loss_norm = torch.norm(vec_high_high - vec_high_up, p=2, dim=-1).mean(-1)
    loss_angle = torch.mul(vec_high_high,vec_high_up).sum(-1) / (torch.norm(vec_high_high, p=2, dim=-1) * torch.norm(vec_high_up, p=2, dim=-1) + 0.00001)
    loss_angle = loss_angle.mean(-1)
    loss = loss_norm.mean() + loss_angle.mean()
    return loss

if __name__ == '__main__':
    pcl_high = torch.randn(2,8,3)
    pcl_up = torch.randn(2,8,3)
    loss = Density_Angle(pcl_high, pcl_up, knn=8)
    print(loss)


from codexbot.services.slack.Bot import Bot
from .message import Message

class Events():

    def __init__(self, slack_event):
        """
        Handle all subsripted events
        @todo: Most functions are useless. Make structure more flexible

        :param slack_event: event params
        """
        self.slack_event  = slack_event
        self.slackBot = Bot()
        self.handle(self.slack_event)

    def handle(self, slack_event):

        """
        get event type and use structured classes to handle events

        :param slack_event:
        :return:
        """
        event = slack_event.get('event')

        if event.get('type') == 'message':
            message = Message()
            message.getMessage(event)
            channel_id = event.get('channel')

            # this is bot message
            # do not listen
            if not event.get('bot_id') and not event.get('bot_message'):
                attachment = {
                            "title":"App hangs on reboot",
                            "title_link": "http://domain.com/ticket/123456",
                            "text": "If I restart my computer without quitting your app, it stops the reboot sequence.\nhttp://domain.com/ticket/123456",
                        }
                self.slackBot.client.api_call(
                    "chat.postMessage",
                    channel=channel_id,
                    text='Would you like to play a game?',
                    attachments=[attachment]
                )

        if event.get('type') == 'reaction_removed':
            print('reaction removed')
        elif event.get('type') == 'reaction_added':
            print('reaction_added')

    def get_bot_id(self, bot_name):
        """
        get bot ID by bot name

        :param bot_name:
        :return:
        """
        members = self.slackBot.client.api_call("users.list")
        if members.get('ok'):
            users = members.get('members')
            for user in users:
                if 'name' in user and user.get('name') == bot_name:
                    print("Bot ID for '" + user['name'] + "' is " + user.get('id'))
            else:
                print("could not find bot user with the name " + bot_name)

    def channels_list(self):
        """
        get teams channel list

        :return:
        """
        channels_list = self.slackBot.client.api_call("channels.list")
        if channels_list.get('ok'):
            return channels_list['channels']
        return None

    def send_message(self, channel_id, message, emoji):
        """
        send message to the channel

        :param channel_id:
        :param message:
        :param emoji:
        :return:
        """
        self.slackBot.client.api_call(
            "chat.postMessage",
            channel=channel_id,
            text=message,
            icon_emoji=':' + emoji,
            as_user=True
        )

    def channels_info(self, channel_id):
        """
        get full information about channel

        :param channel_id:
        :return:
        """
        channel_info = self.slackBot.client.api_call("channels.info", channel=channel_id)
        if channel_info:
            return channel_info
        return None


from abc import ABC, abstractmethod
import numpy as np
from sklearn import datasets
from sklearn.model_selection import StratifiedKFold
from src.constants import *
from src.filters.chi2 import Chi2Filter
from src.filters.pca import PCAFilter

class BaseRunner(ABC):

    def __init__(self) -> None:
        """
        Init of runner. Now create synthetic data.
        """
        super(BaseRunner, self).__init__()
        self.X, self.y = datasets.make_classification(**data_set_values)

        self.skf = StratifiedKFold(
            n_splits=N_SPLITS, shuffle=True, random_state=RANDOM_STATE)

        self.scores = np.zeros(N_SPLITS)

    @abstractmethod
    def run_classifier(self, filter_type: FilterTypes) -> (np.ndarray, np.ndarray):
        """
        Run classifier using filter_type to get mean and std
        :param filter_type:
        :return:
        """
        pass

    def filter_x(self, filter_type: FilterTypes, train):
        """
        Switch case for filtering x
        :param filter_type:
        :param train:
        :return:
        """
        return {
            FilterTypes.NoFilter: self.X,
            FilterTypes.PCA: PCAFilter().filter_x(self.X, train=train),
            FilterTypes.chi2: Chi2Filter().filter_x(self.X, y=self.y),

        }[filter_type]

    def calculate_mean_and_std(self) -> (np.ndarray, np.ndarray):
        """
        Calculate mean and std using list of scores
        :return: Returns means and std
        """
        mean = round(np.mean(self.scores), 2)
        std = round(np.std(self.scores), 3)

        return mean, std


BOARD_SIZE = 8

class BailOut:
    pass

def validate(q):
    left = right = col = q[-1]
    for r in list(reversed(q[:-1])):
        left, right = left-1, right+1
        if r in (left, col, right):
            raise BailOut

def add_queen(q):
    for i in range(BOARD_SIZE):
        test_queens = q + [i]
        validate(test_queens)
        if len(test_queens) == BOARD_SIZE:
            return test_queens
        else:
            return add_queen(test_queens)
    return []

queens = add_queen([])
print(queens)
print("\n".join([". "*q + "Q " + ". "*(BOARD_SIZE-q-1) for q in queens]))

# BOARD_SIZE := int
# BailOut := Type[BailOut]
# add_queen := Callable[[List[int]], List[int]]
# queens := List[int]
# validate := Callable[[List[int]], None]