import os
import cv2
import csv
import json
import natsort
import numpy as np
import xml.dom.minidom as minidom
import xml.etree.ElementTree as ET

from PIL import Image
from datetime import date

from anylabeling.app_info import __version__

class LabelConverter:
    def __init__(self, classes_file=None, mapping_file=None):
        self.classes = []
        if classes_file:
            with open(classes_file, "r", encoding="utf-8") as f:
                self.classes = f.read().splitlines()
        self.mapping_table = None
        if mapping_file:
            with open(mapping_file, "r", encoding="utf-8") as f:
                self.mapping_table = json.load(f)

    def reset(self):
        self.custom_data = dict(
            version=__version__,
            flags={},
            shapes=[],
            imagePath="",
            imageData=None,
            imageHeight=-1,
            imageWidth=-1,
        )

    @staticmethod
    def calculate_polygon_area(segmentation):
        x, y = [], []
        for i in range(len(segmentation)):
            if i % 2 == 0:
                x.append(segmentation[i])
            else:
                y.append(segmentation[i])
        area = 0.5 * np.abs(
            np.dot(x, np.roll(y, 1)) - np.dot(y, np.roll(x, 1))
        )
        return area

    @staticmethod
    def get_image_size(image_file):
        with Image.open(image_file) as img:
            width, height = img.size
            return width, height

    @staticmethod
    def get_min_enclosing_bbox(segmentation):
        if not segmentation:
            return []
        polygon_points = [
            (segmentation[i], segmentation[i + 1])
            for i in range(0, len(segmentation), 2)
        ]
        x_coords, y_coords = zip(*polygon_points)
        x_min = min(x_coords)
        y_min = min(y_coords)
        x_max = max(x_coords)
        y_max = max(y_coords)
        bbox_width = x_max - x_min
        bbox_height = y_max - y_min
        return [x_min, y_min, bbox_width, bbox_height]

    def get_coco_meta_data(self, root_path, formats):
        label_list = []
        basename_to_img_id = {}
        coco_meta_data = {
            "info": {
                "year": 2023,
                "version": __version__,
                "description": "COCO Label Conversion",
                "contributor": "CVHub",
                "url": "https://github.com/CVHub520/X-AnyLabeling",
                "date_created": str(date.today()),
            },
            "licenses": [
                {
                    "id": 1,
                    "url": "https://www.gnu.org/licenses/gpl-3.0.html",
                    "name": "GNU GENERAL PUBLIC LICENSE Version 3",
                }
            ],
            "categories": [],
            "images": [],
            "annotations": [],
        }

        for i, class_name in enumerate(self.classes):
            coco_meta_data["categories"].append(
                {"id": i + 1, "name": class_name, "supercategory": ""}
            )
        image_id = 0
        file_list = os.listdir(root_path)
        file_list = natsort.os_sorted(file_list)
        for file_name in file_list:
            fmt = "*." + file_name.rsplit(".", 1)[-1]
            if fmt.lower() not in formats:
                if fmt == "*.json":
                    label_list.append(file_name)
                continue
            image_id += 1
            image_file = os.path.join(root_path, file_name)
            width, height = self.get_image_size(image_file)
            base_name = os.path.splitext(file_name)[0]
            coco_meta_data["images"].append(
                {
                    "id": image_id,
                    "file_name": base_name,
                    "width": width,
                    "height": height,
                    "license": 0,
                    "flickr_url": "",
                    "coco_url": "",
                    "date_captured": "",
                }
            )
            basename_to_img_id[base_name] = image_id

        return coco_meta_data, label_list, basename_to_img_id

    def custom_to_mot_rectangle(self, data, output_file, base_name):
        frame_id = int(base_name.split("_")[-1][:6])
        mot_data = []
        for shape in data["shapes"]:
            track_id = int(shape["group_id"]) if shape["group_id"] else -1
            class_id = self.classes.index(shape["label"])
            points = shape["points"]
            xmin = points[0][0]
            ymin = points[0][1]
            xmax = points[2][0]
            ymax = points[2][1]
            data = [
                frame_id,
                track_id,
                xmin,
                ymin,
                xmax - xmin,
                ymax - ymin,
                0,
                class_id,
                1,
            ]
            mot_data.append(data)

        # Check if output_file exists
        if os.path.isfile(output_file):
            # Read existing CSV file and update data
            with open(output_file, "r", newline="") as csvfile:
                reader = csv.reader(csvfile, delimiter=",")
                existing_data = [row for row in reader]

            # Check if frame_id exists in existing_data
            frame_ids = set(int(row[0]) for row in existing_data)
            if frame_id in frame_ids:
                # Remove existing data with the same frame_id
                updated_data = [
                    row for row in existing_data if int(row[0]) != frame_id
                ]
                # Insert new mot_data
                updated_data.extend(mot_data)
            else:
                updated_data = existing_data + mot_data
        else:
            updated_data = mot_data

        # Save updated_data to output_file
        with open(output_file, "w", newline="") as csvfile:
            writer = csv.writer(csvfile, delimiter=",")
            writer.writerows(updated_data)

    def custom_to_voc_rectangle(self, data, output_dir):
        image_path = data["imagePath"]
        image_width = data["imageWidth"]
        image_height = data["imageHeight"]

        root = ET.Element("annotation")
        ET.SubElement(root, "folder").text = os.path.dirname(output_dir)
        ET.SubElement(root, "filename").text = os.path.basename(image_path)
        size = ET.SubElement(root, "size")
        ET.SubElement(size, "width").text = str(image_width)
        ET.SubElement(size, "height").text = str(image_height)
        ET.SubElement(size, "depth").text = "3"

        for shape in data["shapes"]:
            label = shape["label"]
            points = shape["points"]
            difficult = shape.get("difficult", False)

            xmin = str(points[0][0])
            ymin = str(points[0][1])
            xmax = str(points[2][0])
            ymax = str(points[2][1])

            object_elem = ET.SubElement(root, "object")
            ET.SubElement(object_elem, "name").text = label
            ET.SubElement(object_elem, "pose").text = "Unspecified"
            ET.SubElement(object_elem, "truncated").text = "0"
            ET.SubElement(object_elem, "difficult").text = str(int(difficult))
            bndbox = ET.SubElement(object_elem, "bndbox")
            ET.SubElement(bndbox, "xmin").text = xmin
            ET.SubElement(bndbox, "ymin").text = ymin
            ET.SubElement(bndbox, "xmax").text = xmax
            ET.SubElement(bndbox, "ymax").text = ymax

        xml_string = ET.tostring(root, encoding="utf-8")
        dom = minidom.parseString(xml_string)
        formatted_xml = dom.toprettyxml(indent="  ")

        with open(output_dir, "w") as f:
            f.write(formatted_xml)

    def custom_to_dota(self, data, output_file):
        with open(output_file, "w", encoding="utf-8") as f:
            for shape in data["shapes"]:
                label = shape["label"]
                points = shape["points"]
                difficult = shape.get("difficult", False)

                # Skip shapes with negative coordinates
                if any(coord < 0 for point in points for coord in point):
                    continue

                x0 = points[0][0]
                y0 = points[0][1]
                x1 = points[1][0]
                y1 = points[1][1]
                x2 = points[2][0]
                y2 = points[2][1]
                x3 = points[3][0]
                y3 = points[3][1]
                f.write(
                    f"{x0} {y0} {x1} {y1} {x2} {y2} {x3} {y3} {label} {int(difficult)}\n"
                )

    def custom_to_yolo_rectangle(self, data, output_file):
        image_width = data["imageWidth"]
        image_height = data["imageHeight"]
        with open(output_file, "w", encoding="utf-8") as f:
            for shape in data["shapes"]:
                label = shape["label"]
                points = shape["points"]
                class_index = self.classes.index(label)
                x_center = (points[0][0] + points[2][0]) / (2 * image_width)
                y_center = (points[0][1] + points[2][1]) / (2 * image_height)
                width = abs(points[2][0] - points[0][0]) / image_width
                height = abs(points[2][1] - points[0][1]) / image_height
                f.write(
                    f"{class_index} {x_center} {y_center} {width} {height}\n"
                )

    def custom_to_yolo_polygon(self, data, output_file):
        image_width = data["imageWidth"]
        image_height = data["imageHeight"]
        image_size = np.array([[image_width, image_height]])

        with open(output_file, "w", encoding="utf-8") as f:
            for shape in data["shapes"]:
                label = shape["label"]
                points = np.array(shape["points"])
                class_index = self.classes.index(label)
                norm_points = points / image_size
                f.write(
                    f"{class_index} "
                    + " ".join(
                        [
                            " ".join([str(cell[0]), str(cell[1])])
                            for cell in norm_points.tolist()
                        ]
                    )
                    + "\n"
                )

    def custom_to_coco(self, root_path, output_file, formats):
        (
            coco_meta_data,
            label_list,
            basename_to_img_id,
        ) = self.get_coco_meta_data(root_path, formats)
        # Loop the label_list
        annotation_id = 0
        for file_name in label_list:
            # Load custom data
            input_file = os.path.join(root_path, file_name)
            with open(input_file, "r", encoding="utf-8") as f:
                data = json.load(f)
            # Extract the basename
            basename = os.path.splitext(file_name)[0]
            # Loop the shapes
            for shape in data["shapes"]:
                annotation_id += 1
                label = shape["label"]
                points = shape["points"]
                difficult = shape.get("difficult", False)
                class_id = self.classes.index(label)
                annotation = {
                    "id": annotation_id,
                    "image_id": basename_to_img_id[basename],
                    "category_id": class_id + 1,
                    "iscrowd": 0,
                    "ignore": int(difficult),
                }
                if shape["shape_type"] == "rectangle":
                    x_min = min(points[0][0], points[2][0])
                    y_min = min(points[0][1], points[2][1])
                    x_max = max(points[0][0], points[2][0])
                    y_max = max(points[0][1], points[2][1])
                    width = x_max - x_min
                    height = y_max - y_min
                    area = width * height
                    bbox = [x_min, y_min, width, height]
                    annotation["bbox"] = bbox
                    annotation["area"] = area
                elif shape["shape_type"] == "polygon":
                    segmentation = []
                    for point in points:
                        x, y = point
                        segmentation.append(x)
                        segmentation.append(y)
                    annotation["segmentation"] = [segmentation]
                    annotation["bbox"] = self.get_min_enclosing_bbox(
                        segmentation
                    )
                    annotation["area"] = self.calculate_polygon_area(
                        segmentation
                    )
                coco_meta_data["annotations"].append(annotation)

        # Save the coco result
        with open(output_file, "w", encoding="utf-8") as f:
            json.dump(coco_meta_data, f, indent=4, ensure_ascii=False)

    def custom_polygon_to_mask(self, data, output_file):
        image_width = data["imageWidth"]
        image_height = data["imageHeight"]
        image_shape = (image_height, image_width)

        polygons = {}
        for shape in data["shapes"]:
            points = shape["points"]
            polygon = []
            for point in points:
                x, y = point
                polygon.append((int(x), int(y)))  # Convert to integers
            polygons[shape["label"]] = polygon

        output_format = self.mapping_table["type"]
        if output_format not in ["grayscale", "rgb"]:
            raise ValueError("Invalid output format specified")
        mapping_color = self.mapping_table["colors"]

        if output_format == "grayscale":
            binary_mask = np.zeros(image_shape, dtype=np.uint8)
            for label, polygon in polygons.items():
                mask = np.zeros(image_shape, dtype=np.uint8)
                cv2.fillPoly(mask, [np.array(polygon, dtype=np.int32)], 1)
                if label in mapping_color:
                    mask_mapped = mask * mapping_color[label]
                else:
                    mask_mapped = mask
                binary_mask += mask_mapped
            cv2.imwrite(output_file, binary_mask)
        elif output_format == "rgb":
            # Initialize rgb_mask
            color_mask = np.zeros(
                (image_height, image_width, 3), dtype=np.uint8
            )
            for label, polygon in polygons.items():
                # Create a mask for each polygon
                mask = np.zeros(image_shape[:2], dtype=np.uint8)
                cv2.fillPoly(mask, [np.array(polygon, dtype=np.int32)], 1)
                # Initialize mask_mapped with a default value
                mask_mapped = mask
                # Map the mask values using the provided mapping table
                if label in mapping_color:
                    color = mapping_color[label]
                    mask_mapped = np.zeros_like(color_mask)
                    cv2.fillPoly(
                        mask_mapped, [np.array(polygon, dtype=np.int32)], color
                    )
                    color_mask = cv2.addWeighted(
                        color_mask, 1, mask_mapped, 1, 0
                    )
            cv2.imwrite(
                output_file, cv2.cvtColor(color_mask, cv2.COLOR_BGR2RGB)
            )

    def yolo_to_custom(self, input_file, output_file, image_file):
        self.reset()
        with open(input_file, "r", encoding="utf-8") as f:
            lines = f.readlines()
        img_w, img_h = self.get_image_size(image_file)

        for line in lines:
            line = line.strip().split(" ")
            class_index = int(line[0])
            cx = float(line[1])
            cy = float(line[2])
            nw = float(line[3])
            nh = float(line[4])
            xmin = int((cx - nw / 2) * img_w)
            ymin = int((cy - nh / 2) * img_h)
            xmax = int((cx + nw / 2) * img_w)
            ymax = int((cy + nh / 2) * img_h)

            shape_type = "rectangle"
            label = self.classes[class_index]
            points = [
                [xmin, ymin],
                [xmax, ymin],
                [xmax, ymax],
                [xmin, ymax],
            ]
            shape = {
                "label": label,
                "shape_type": shape_type,
                "flags": {},
                "points": points,
                "group_id": None,
                "description": None,
                "difficult": False,
                "attributes": {},
            }
            self.custom_data["shapes"].append(shape)
        self.custom_data["imagePath"] = os.path.basename(image_file)
        self.custom_data["imageHeight"] = img_h
        self.custom_data["imageWidth"] = img_w
        with open(output_file, "w", encoding="utf-8") as f:
            json.dump(self.custom_data, f, indent=2, ensure_ascii=False)

    def voc_to_custom(self, input_file, output_file):
        self.reset()

        tree = ET.parse(input_file)
        root = tree.getroot()

        image_path = root.find("filename").text
        image_width = int(root.find("size/width").text)
        image_height = int(root.find("size/height").text)

        self.custom_data["imagePath"] = image_path
        self.custom_data["imageHeight"] = image_height
        self.custom_data["imageWidth"] = image_width

        for obj in root.findall("object"):
            label = obj.find("name").text
            difficult = "0"
            if obj.find("difficult") is not None:
                difficult = str(obj.find("difficult").text)
            xmin = float(obj.find("bndbox/xmin").text)
            ymin = float(obj.find("bndbox/ymin").text)
            xmax = float(obj.find("bndbox/xmax").text)
            ymax = float(obj.find("bndbox/ymax").text)

            shape = {
                "label": label,
                "description": "",
                "points": [
                    [xmin, ymin],
                    [xmax, ymin],
                    [xmax, ymax],
                    [xmin, ymax],
                ],
                "group_id": None,
                "difficult": bool(int(difficult)),
                "shape_type": "rectangle",
                "flags": {},
            }

            self.custom_data["shapes"].append(shape)

        with open(output_file, "w", encoding="utf-8") as f:
            json.dump(self.custom_data, f, indent=2, ensure_ascii=False)

    def coco_to_custom(self, input_file, image_path):
        with open(input_file, "r", encoding="utf-8") as f:
            data = json.load(f)

        if not self.classes:
            for cat in data["categories"]:
                self.classes.append(cat["name"])

        total_info, label_info = {}, {}

        # map category_id to name
        for dic_info in data["categories"]:
            label_info[dic_info["id"]] = dic_info["name"]

        # map image_id to info
        for dic_info in data["images"]:
            total_info[dic_info["id"]] = {
                "imageWidth": dic_info["width"],
                "imageHeight": dic_info["height"],
                "imagePath": os.path.basename(dic_info["file_name"]),
                "shapes": [],
            }

        for dic_info in data["annotations"]:
            bbox = dic_info["bbox"]
            xmin = bbox[0]
            ymin = bbox[1]
            width = bbox[2]
            height = bbox[3]
            xmax = xmin + width
            ymax = ymin + height

            shape_type = "rectangle"
            difficult = bool(int(str(dic_info.get("ignore", "0"))))
            label = self.classes[dic_info["category_id"] - 1]
            points = [
                [xmin, ymin],
                [xmax, ymin],
                [xmax, ymax],
                [xmin, ymax],
            ]
            shape = {
                "label": label,
                "shape_type": shape_type,
                "flags": {},
                "points": points,
                "group_id": None,
                "description": None,
                "difficult": difficult,
                "attributes": {},
            }

            total_info[dic_info["image_id"]]["shapes"].append(shape)

        for dic_info in total_info.values():
            self.reset()
            self.custom_data["shapes"] = dic_info["shapes"]
            self.custom_data["imagePath"] = dic_info["imagePath"]
            self.custom_data["imageHeight"] = dic_info["imageHeight"]
            self.custom_data["imageWidth"] = dic_info["imageWidth"]

            output_file = os.path.join(
                image_path, os.path.splitext(dic_info["imagePath"])[0] + ".json"
            )
            with open(output_file, "w", encoding="utf-8") as f:
                json.dump(self.custom_data, f, indent=2, ensure_ascii=False)


from abc import ABC, abstractmethod

import attrs

from data_diff.abcs.database_types import (
    Array,
    TemporalType,
    FractionalType,
    ColType_UUID,
    Boolean,
    ColType,
    String_UUID,
    JSON,
    Struct,
)
from data_diff.abcs.compiler import Compilable

@attrs.define(frozen=False)
class AbstractMixin(ABC):
    "A mixin for a database dialect"

@attrs.define(frozen=False)
class AbstractMixin_NormalizeValue(AbstractMixin):
    @abstractmethod
    def to_comparable(self, value: str, coltype: ColType) -> str:
        """Ensure that the expression is comparable in ``IS DISTINCT FROM``."""

    @abstractmethod
    def normalize_timestamp(self, value: str, coltype: TemporalType) -> str:
        """Creates an SQL expression, that converts 'value' to a normalized timestamp.

        The returned expression must accept any SQL datetime/timestamp, and return a string.

        Date format: ``YYYY-MM-DD HH:mm:SS.FFFFFF``

        Precision of dates should be rounded up/down according to coltype.rounds
        """

    @abstractmethod
    def normalize_number(self, value: str, coltype: FractionalType) -> str:
        """Creates an SQL expression, that converts 'value' to a normalized number.

        The returned expression must accept any SQL int/numeric/float, and return a string.

        Floats/Decimals are expected in the format
        "I.P"

        Where I is the integer part of the number (as many digits as necessary),
        and must be at least one digit (0).
        P is the fractional digits, the amount of which is specified with
        coltype.precision. Trailing zeroes may be necessary.
        If P is 0, the dot is omitted.

        Note: We use 'precision' differently than most databases. For decimals,
        it's the same as ``numeric_scale``, and for floats, who use binary precision,
        it can be calculated as ``log10(2**numeric_precision)``.
        """

    def normalize_boolean(self, value: str, _coltype: Boolean) -> str:
        """Creates an SQL expression, that converts 'value' to either '0' or '1'."""
        return self.to_string(value)

    def normalize_uuid(self, value: str, coltype: ColType_UUID) -> str:
        """Creates an SQL expression, that strips uuids of artifacts like whitespace."""
        if isinstance(coltype, String_UUID):
            return f"TRIM({value})"
        return self.to_string(value)

    def normalize_json(self, value: str, _coltype: JSON) -> str:
        """Creates an SQL expression, that converts 'value' to its minified json string representation."""
        return self.to_string(value)

    def normalize_array(self, value: str, _coltype: Array) -> str:
        """Creates an SQL expression, that serialized an array into a JSON string."""
        return self.to_string(value)

    def normalize_struct(self, value: str, _coltype: Struct) -> str:
        """Creates an SQL expression, that serialized a typed struct into a JSON string."""
        return self.to_string(value)

    def normalize_value_by_type(self, value: str, coltype: ColType) -> str:
        """Creates an SQL expression, that converts 'value' to a normalized representation.

        The returned expression must accept any SQL value, and return a string.

        The default implementation dispatches to a method according to `coltype`:

        ::

            TemporalType    -> normalize_timestamp()
            FractionalType  -> normalize_number()
            *else*          -> to_string()

            (`Integer` falls in the *else* category)

        """
        if isinstance(coltype, TemporalType):
            return self.normalize_timestamp(value, coltype)
        elif isinstance(coltype, FractionalType):
            return self.normalize_number(value, coltype)
        elif isinstance(coltype, ColType_UUID):
            return self.normalize_uuid(value, coltype)
        elif isinstance(coltype, Boolean):
            return self.normalize_boolean(value, coltype)
        elif isinstance(coltype, JSON):
            return self.normalize_json(value, coltype)
        elif isinstance(coltype, Array):
            return self.normalize_array(value, coltype)
        elif isinstance(coltype, Struct):
            return self.normalize_struct(value, coltype)
        return self.to_string(value)

@attrs.define(frozen=False)
class AbstractMixin_MD5(AbstractMixin):
    """Methods for calculating an MD6 hash as an integer."""

    @abstractmethod
    def md5_as_int(self, s: str) -> str:
        "Provide SQL for computing md5 and returning an int"

@attrs.define(frozen=False)
class AbstractMixin_Schema(AbstractMixin):
    """Methods for querying the database schema

    TODO: Move AbstractDatabase.query_table_schema() and friends over here
    """

    def table_information(self) -> Compilable:
        "Query to return a table of schema information about existing tables"
        raise NotImplementedError()

    @abstractmethod
    def list_tables(self, table_schema: str, like: Compilable = None) -> Compilable:
        """Query to select the list of tables in the schema. (query return type: table[str])

        If 'like' is specified, the value is applied to the table name, using the 'like' operator.
        """

@attrs.define(frozen=False)
class AbstractMixin_RandomSample(AbstractMixin):
    @abstractmethod
    def random_sample_n(self, tbl: str, size: int) -> str:
        """Take a random sample of the given size, i.e. return 'size' amount of rows"""

    @abstractmethod
    def random_sample_ratio_approx(self, tbl: str, ratio: float) -> str:
        """Take a random sample of the approximate size determined by the ratio (0..1), where 0 means no rows, and 1 means all rows

        i.e. the actual mount of rows returned may vary by standard deviation.
        """

    # def random_sample_ratio(self, table: ITable, ratio: float):
    #     """Take a random sample of the size determined by the ratio (0..1), where 0 means no rows, and 1 means all rows
    #     """

@attrs.define(frozen=False)
class AbstractMixin_TimeTravel(AbstractMixin):
    @abstractmethod
    def time_travel(
        self,
        table: Compilable,
        before: bool = False,
        timestamp: Compilable = None,
        offset: Compilable = None,
        statement: Compilable = None,
    ) -> Compilable:
        """Selects historical data from a table

        Parameters:
            table - The name of the table whose history we're querying
            timestamp - A constant timestamp
            offset - the time 'offset' seconds before now
            statement - identifier for statement, e.g. query ID

        Must specify exactly one of `timestamp`, `offset` or `statement`.
        """

@attrs.define(frozen=False)
class AbstractMixin_OptimizerHints(AbstractMixin):
    @abstractmethod
    def optimizer_hints(self, optimizer_hints: str) -> str:
        """Creates a compatible optimizer_hints string

        Parameters:
            optimizer_hints - string of optimizer hints
        """


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

__author__ = "You-Sheng Lin"
__copyright__ = "Copyright (C) 2019"
__license__ = "AGPL"
__email__ = "pyquino@gmail.com"

from math import ceil, sqrt, hypot
import matplotlib.pyplot as plt

sampling_time = 0.001
Amax = 2500

def interpolation_2d(ox, oy, x, y, f):

    length = hypot((x - ox), (y - oy))
    Nc = 0
    amax = Amax
    N_start = ceil(f / (amax * sampling_time))
    Tstr = N_start * sampling_time
    L_min = f * Tstr

    Lsblk = 0.0
    Nss = 0.0

    if length <= L_min:
        N_start = ceil(sqrt(length / (amax * sampling_time * sampling_time)))
        Tstr = N_start * sampling_time
        Tc = Nc * sampling_time
        V_cmd = length / Tstr
        Lest = V_cmd * Tstr
    else:
        Nc = ceil((length - L_min) / (f * sampling_time))
        Tc = Nc * sampling_time
        V_cmd = length / (Tstr + Tc)
        Lest = V_cmd * (Tstr + Tc)

    L1 = 0.5 * V_cmd * Tstr
    L2 = V_cmd * (Tstr + Tc)
    step1 = N_start
    step2 = step1 + Nc
    step3 = step2 + N_start
    t0 = 0
    t1 = step1 * sampling_time
    t2 = step2 * sampling_time
    t3 = step3 * sampling_time

    f = V_cmd
    a = V_cmd / Tstr
    j = a / sampling_time
    s_tmp = []
    v_tmp = []
    acc_tmp = []
    for i in range(step3):

        t = i * sampling_time
        if i < step1:
            acc = a
            fed = acc * t
            pos = 0.5 * acc * t * t

        elif step1 <= i <= step2:
            acc = 0
            fed = f
            pos = L1 + fed * (t - t1)

        else:
            acc = -a
            fed = a * (t3 - t)
            pos = L2 - 0.5 * a * (t3 - t) * (t3 - t)

        s_tmp.append(pos)
        v_tmp.append(fed)
        acc_tmp.append(acc)

    plt.plot(list(i * 0.001 for i in range(len(s_tmp))), s_tmp)
    plt.show()

def s_shape_interplation(ox, oy, x, y, f):

    length = hypot((x - ox), (y - oy))
    Nss = 0
    Nc = 0
    amax = Amax
    # need to define Jmax
    Jmax = 50000
    Lmin = 2 * f * sqrt(f / Jmax)
    Nstr = ceil((Lmin / 2 / Jmax / sampling_time ** 3) ** (1 / 3))
    Tstr = Nstr * sampling_time

    if length <= Lmin:
        Nstr = ceil((length / 2 / Jmax / sampling_time ** 3) ** (1 / 3))
        Tstr = Nstr * sampling_time
        Jmax = length / (2 * Tstr ** 3)
        amax = Jmax * Tstr
        Vcmd = amax * Tstr
    else:
        Tc = length / f - 2 * Tstr
        Nc = ceil(Tc / sampling_time)
        Tc = Nc * sampling_time
        Vcmd = length / (2 * Tstr + Tc)
        amax = Vcmd / Tstr
        Jmax = amax / Tstr

    step1 = Nstr
    step2 = step1 + Nstr
    step3 = step2 + Nc
    step4 = step3 + Nstr
    step5 = step4 + Nstr

    t0 = 0
    t1 = step1 * sampling_time
    t2 = step2 * sampling_time
    t3 = step3 * sampling_time
    t4 = step4 * sampling_time
    t5 = step5 * sampling_time

    pos1 = (Jmax * (t1 - t0) ** 3) / 6
    pos2 = pos1 + Vcmd * (t2 - t1) - 0.5 * Jmax * (t2 ** 2 * (t2 - t1) - t2 *
                                                   (t2 ** 2 - t1 ** 2) + (t2 ** 3 - t1 ** 3) / 3)
    pos3 = pos2 + Vcmd * (t3 - t2)
    pos4 = pos3 + Vcmd * (t4 - t3) - (Jmax * (t4 - t3) ** 3 / 6)
    pos5 = pos4 + 0.5 * Jmax * (t5 ** 2 * (t5 - t4) - t5 * (t5 ** 2 - t4 ** 2) + ((t5 ** 3 - t4 ** 3) / 3))

    s_tmp = []
    v_tmp = []
    acc_tmp = []
    jerk_tmp = []

    for j in range(step5):
        t = j * sampling_time
        if j < step1:
            jerk = Jmax
            acc = Jmax * (t - t0)
            fed = 0.5 * Jmax * (t - t0) ** 2
            pos = (Jmax * (t-t0) ** 3)/6
        elif step1 <= j < step2:
            jerk = -Jmax
            acc = Jmax * (t2 - t)
            fed = Vcmd - 0.5 * Jmax * (t2 - t) ** 2
            pos = pos1 + Vcmd * (t - t1) - 0.5 * Jmax * (
                        t2 ** 2 * (t - t1) - t2 * (t ** 2 - t1 ** 2) + (t ** 3 - t1 ** 3) / 3)
        elif step2 <= j < step3:
            jerk = 0
            acc = 0
            fed = Vcmd
            pos = pos2 + Vcmd * (t - t2)
        elif step3 <= j < step4:
            jerk = -Jmax
            acc = -Jmax * (t - t3)
            fed = Vcmd - 0.5 * Jmax * (t - t3) ** 2
            pos = pos3 + Vcmd * (t - t3) - (Jmax * (t - t3) ** 3 / 6)
        elif j >= step4:
            jerk = Jmax
            acc = -Jmax * (t5 - t)
            fed = 0.5 * Jmax * (t5 - t) ** 2
            pos = pos4 + 0.5 * Jmax * (t5 ** 2 * (t - t4) - t5 * (t ** 2 - t4 ** 2) + ((t ** 3 - t4 ** 3) / 3))

        else:
            raise ValueError

        s_tmp.append(pos)
        v_tmp.append(fed)
        acc_tmp.append(acc)
        jerk_tmp.append(jerk)

    return s_tmp, v_tmp, acc_tmp, jerk_tmp

if __name__ == '__main__':
    from nc import nc_reader
    with open("../line.nc") as textfile:
        text = textfile.read()
    s_plot = []
    v_plot = []
    a_plot = []
    j_plot = []
    for ox, oy, x, y, of in nc_reader(text):
        # interpolation_2d(ox, oy, x, y, of)
        s, v, a, j = s_shape_interplation(ox, oy, x, y, of)
        s_plot.extend(s)
        v_plot.extend(v)
        a_plot.extend(a)
        j_plot.extend(j)
    plt.plot(list(i * 0.001 for i in range(len(s_plot))), s_plot)
    plt.show()


# Prim's algorithm #
# Time: O(N^2 * log(N))
# Space: O(N^2)
import heapq
from collections import defaultdict
points=[[0,0],[2,2],[3,10],[5,2],[7,0]]
N=len(points)
#https://leetcode.com/problems/min-cost-to-connect-all-points/solution/
### Actually dont even need adjacency list
adj=defaultdict(list)
for i in range(N):
    for j in range(i+1,N):
        cost = abs(points[i][0]-points[j][0]) + abs(points[i][1]-points[j][1])
        adj[i].append([cost,j])
        adj[j].append([cost,i])
h=[[0,0]]
visited=set()
res=0
# while h:
c=0
while len(visited)<N: # This is more optimized
# while h:
    c+=1
    cost, node = heapq.heappop(h)
    if node in visited:
        continue
    visited.add(node)
    res+=cost
    for childcost, child in adj[node]:
        if child not in visited:
            heapq.heappush(h,[childcost,child])
print(res,c)


# Write a function that receives two strings and returns n, where n is equal to the number of characters we should
# shift the first string forward to match the second.
#
# For instance, take the strings "fatigue" and "tiguefa". In this case, the first string has been rotated 5 characters
# forward to produce the second string, so 5 would be returned.
#
# If the second string isn't a valid rotation of the first string, the method returns -1.
# Examples:
# ``` "coffee", "eecoff" => 2 "eecoff", "coffee" => 4 "moose", "Moose" => -1 "isn't", "'tisn" => 2
# "Esham", "Esham" => 0 "dog", "god" => -1 ```
#
# shiftedDiff("coffee", "eecoff") => 2
# shiftedDiff("eecoff", "coffee") => 4
# shiftedDiff("moose", "Moose") => nil
# shiftedDiff("isn't", "'tisn") => 2
# shiftedDiff("Esham", "Esham") => 0
# shiftedDiff("dogg", "godd") => nil

def shiftedDiff(x, y):
    # We need to know if both these list have identical letters, but also we need to figure out if the sequence of
    # the letters are in order we can loop in the first one check if the letter exists in the other list, when we get
    # the first occurence of each we can save their difference
    if len(x) != len(y):
        return -1
    index_first = []
    index_second = []
    # new_list = [a for a in x if a in y]
    for i in range(0, len(x)):
        for n in range(0, len(y)):
            # print(i)
            # first check if letters exits in both strings
            if x[i] == y[n] and n not in index_second and i not in index_first:
                # print(f"this is i {i}")
                index_first.append(i)
                index_second.append(n)
    # we have a list numbers for both lists
    # print(f"this is new list {new_list}")
    # if sorted(x) == sorted(y): #trick
    #     print("same characters")
    print(f"this is index 2 {index_second}")
    print(f"this is index 1 {index_first}")
    if len(index_first) != len(x) and len(index_second) != len(y):
        return -1
    #difference can only have two values: + and - (+ list length to make +)

# print(shiftedDiff("dog", "god"))
print(shiftedDiff("eecoff", "coffee"))
# when there are two of the same letters it freaks out.


# Title:      Medium Asteroid Class
# Filename:   medium.py
# Purpose:    Creates a
#             class for a
#             medium asteroid
#             object to be used in
#             the asteroid program.
# Date:       03/01/2021
###############################################
import arcade
import constants
import math
import random
from asteroid import Asteroid
from small import SmallAsteroid

class MediumAsteroid(Asteroid):
    """
    Initializes a medium
    asteroid.
    """
    def __init__(self, large_rock, order):
        super().__init__()
        self.img       = "images\meteorGrey_med1.png"
        self.texture   = arcade.load_texture(self.img)
        self.height    = self.texture.height
        self.width     = self.texture.width
        self.radius    = constants.MEDIUM_ROCK_RADIUS
        self.speed     = constants.BIG_ROCK_SPEED
        self.center.x  = large_rock.center.x
        self.center.y  = large_rock.center.y
        self.direction = large_rock.direction
        self.type      = constants.ASTRD_MD_TYPE

        if order == 1:
            # The first medium asteroid has the same velocity as the
            # original large one plus 2 pixel/frame in the up direction.
            self.velocity.dx = large_rock.velocity.dx
            self.velocity.dy = large_rock.velocity.dy + constants.MEDIUM_ROCK_DY1
        else:
            # The second medium asteroid has the same velocity as the
            # original large one plus 2 pixel/frame in the down direction.
            self.velocity.dx = large_rock.velocity.dx
            self.velocity.dy = large_rock.velocity.dy - constants.MEDIUM_ROCK_DY1

    def hit(self):
        """
        Updates the score
        and breaks up a
        large asteroid into
        smaller asteroids.
        """

        self.alive = False
        return self.points

    def break_apart(self):
        """
        Medium asteroids
        break apart
        into two small
        asteroids.
        """
        two_small_asteroids = []
        asteroid_sma2 = SmallAsteroid(self, 2)
        asteroid_sma3 = SmallAsteroid(self, 3)
        two_small_asteroids.append(asteroid_sma2)
        two_small_asteroids.append(asteroid_sma2)
        return two_small_asteroids


"""
Напишите программу, которая выводит часть последовательности 1 2 2 3 3 3 4 4 4 4 5 5 5 5 5 ...
(число повторяется столько раз, чему равно).
На вход программе передаётся неотрицательное целое число n — столько элементов
последовательности должна отобразить программа.
На выходе ожидается последовательность чисел, записанных через пробел в одну строку.

Например, если n = 7, то программа должна вывести 1 2 2 3 3 3 4.

Sample Input: 7
Sample Output: 1 2 2 3 3 3 4
"""

num = int(input())
i, n, br = 1, 0, 0
while i <= num:
    j = 1
    n += 1
    while j <= n:
        if br == num:
            break
        print(n, end=' ')
        br += 1
        j += 1
    i += 1

# ВАриант покороче и работает быстрее:

n = int(input())
a = []
i = 0
while len(a) < n:
    a += [i] * i
    i += 1
print(*a[:n])   # * передает в print “неопределеннше количество позиционных или именованных аргументов“,
                # т. е. нашего списка и означает "распаковать список"


from matplotlib import pyplot as plt
from sklearn.preprocessing import LabelBinarizer
from sklearn.metrics import roc_curve, auc, roc_auc_score
import numpy as np

def multiclass_roc_auc_score(y_test, y_pred, target_list, multiclass=True, average="macro"):
    #returns roc_auc score and plots roc curve
    plt.figure(figsize=(6, 6))

    if multiclass:
        lb = LabelBinarizer()
        lb.fit(y_test)
        y_test = lb.transform(y_test)
        y_pred = lb.transform(y_pred)

        for (idx, c_label) in enumerate(target_list):
            fpr, tpr, thresholds = roc_curve(y_test[idx, :], y_pred[idx, :])
            plt.plot(fpr, tpr, label='%s (AUC:%0.2f)' % (c_label, auc(fpr, tpr)))

    else:
        fpr, tpr, thresholds = roc_curve(y_test, y_pred)
        plt.plot(fpr, tpr, label='AUC:%0.2f' % auc(fpr, tpr))

    plt.plot(fpr, fpr, 'b-', label='Random Guessing')
    plt.legend()
    plt.xlabel('False Positive Rate')
    plt.ylabel('True Positive Rate')
    plt.show()

    return roc_auc_score(y_test, y_pred, average=average)

def get_errors(x_test, test_probs, pred_probs, num_errors=4):
    """
    x_test is test dataset

    test_probs and pred_probs are respectively the one hot encoded test labes and
    the predicted probabilities vectors (arranged in a tensor) that the sofmtax gives at test time

    num_errors is how many misslabeled images to show
    """

    test_labels = np.argmax(test_probs, axis=1)
    pred_labels = np.argmax(pred_probs, axis=1)

    error_labels = (pred_labels - test_labels != 0)

    pred_probs_errors = pred_probs[error_labels]
    test_labels_errors = test_labels[error_labels]
    pred_labels_errors = pred_labels[error_labels]
    x_test_errors = x_test[error_labels]

    # Probabilities of the wrong predicted numbers
    y_pred_errors_prob = np.max(pred_probs_errors, axis=1)

    # Predicted probabilities of the true values in the error set
    true_prob_errors = np.diagonal(np.take(pred_probs_errors, test_labels_errors, axis=1))

    # Difference between the probability of the predicted label and the true label
    delta_pred_true_errors = y_pred_errors_prob - true_prob_errors

    # Sorted list of the delta prob errors
    sorted_delta_errors = np.argsort(delta_pred_true_errors)

    # Top errors
    most_important_errors = sorted_delta_errors[-num_errors:]

    return most_important_errors, pred_probs_errors, test_labels_errors, x_test_errors, pred_labels_errors

def display_errors(target_dict, x_test, test_labels, predictions, nrows=2, ncols=2):
    """
    target_dict is a dictionary that associates numbers from 0 to num classes to
    the name of the classes e.g.

    target_dict = {
        '0': class_0,
        '1': class_1,
     ...etc
    }
    """

    n = 0
    fig, ax = plt.subplots(nrows, ncols)
    fig.subplots_adjust(hspace=0.5, wspace=0.5)

    errors_index, \
    pred_probs_errors, \
    test_labels_errors, \
    img_errors, \
    pred_labels_errors = get_errors(x_test, test_labels, predictions)

    for row in range(nrows):
        for col in range(ncols):
            error = errors_index[n]
            ax[row, col].imshow(img_errors[error])
            ax[row, col].set_title("Predicted label: {}\nTrue label: {}".format(target_dict[str(pred_labels_errors[error])],
                                                                                target_dict[str(test_labels_errors[error])]))
            n += 1

    plt.show()


from PyQt6.QtWidgets import QApplication, QPushButton, QMainWindow, QVBoxLayout, QWidget, QLabel, QColorDialog, QHBoxLayout
from PyQt6.QtCore import QTimer
import sys
import glob
from time import sleep
import serial
import threading

def setInterval(func,time):
    e = threading.Event()
    while not e.wait(time):
        func()

def serial_ports():
    if sys.platform.startswith('win'):
        ports = ['COM%s' % (i + 1) for i in range(256)]
    elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
        ports = glob.glob('/dev/tty[A-Za-z]*')
    elif sys.platform.startswith('darwin'):
        ports = glob.glob('/dev/tty.*')
    else:
        raise EnvironmentError('Unsupported platform')

    result = []
    for port in ports:
        try:
            s = serial.Serial(port)
            s.close()
            result.append(port)
        except (OSError, serial.SerialException):
            pass
    return result

ser = serial.Serial(serial_ports()[0], 115200)

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.currentData = []
        ser.write(bytearray([0xFF]))
        self.get_data()

        self.temp = QLabel("Температура воздуха: " + str(self.currentData[3]) + "°C")
        self.humidity = QLabel("Влажность воздуха: " + str(self.currentData[-3]) + "%")

        self.airLayout = QHBoxLayout()
        self.airLayout.addWidget(self.temp)
        self.airLayout.addWidget(self.humidity)

        self.pressure = QLabel("Давление воздуха: " + str(self.currentData[5]) + "hPa")
        self.soiltemp = QLabel("Температура почвы: " + str(self.currentData[9]) + "°C")

        self.soilLayout = QHBoxLayout()
        self.soilLayout.addWidget(self.pressure)
        self.soilLayout.addWidget(self.soiltemp)

        self.soilhumidity = QLabel("Влажость почвы: " + str(self.currentData[10]) + "%")
        self.light = QLabel("Интенсивность света: " + str(self.currentData[6]) + "Люкс")

        self.otherLayout = QHBoxLayout()
        self.otherLayout.addWidget(self.soilhumidity)
        self.otherLayout.addWidget(self.light)

        self.color = QColorDialog()

        self.submitColor = QPushButton("Задать цвет")
        self.submitColor.clicked.connect(self.onSubmitColor)

        self.signalButton = QPushButton("Включить сирену" if self.currentData[-6] == 0 else "Выключить сирену")
        self.signalButton.clicked.connect(self.onsignalButtonClick)

        self.windButton = QPushButton("Включить вентилятор" if self.currentData[-2] == 0 else "Выключить вентилятор")
        self.windButton.clicked.connect(self.onWindButtonClick)

        self.doorButton = QPushButton("Закрыть дверь" if self.currentData[-1] == 32 else "Открыть дверь")
        self.doorButton.clicked.connect(self.ondoorButtonClick)

        self.melodyButton = QPushButton("Включить мелодию")
        self.melodyButton.clicked.connect(self.onMelodyButtonClick)

        layout = QVBoxLayout()
        layout.addWidget(self.humidity)
        layout.addWidget(self.color)
        layout.addWidget(self.submitColor)
        layout.addWidget(self.signalButton)
        layout.addWidget(self.windButton)
        layout.addWidget(self.doorButton)
        layout.addWidget(self.melodyButton)

        container = QWidget()
        container.setLayout(layout)

        self.setWindowTitle("Умный дом")

        self.timer = QTimer()
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self.updateData)
        self.timer.start()

        self.setCentralWidget(container)

    def updateData(self):
        ser.write(bytearray([0xFF]))
        self.get_data()
        self.reloadSensors()

    def reloadSensors(self):
        self.humidity.setText("Влажность воздуха: " + str(self.currentData[-3]) + "%")

    def onSubmitColor(self):
        _currentColor = self.color.currentColor()
        _writeRGB = bytearray([0xA3])
        self.reloadSensors()

        _writeRGB.append(_currentColor.red())
        _writeRGB.append(_currentColor.green())
        _writeRGB.append(_currentColor.blue())

        ser.write(_writeRGB)
        self.get_data()
        self.color.show()

    def onsignalButtonClick(self):
        ser.write(bytearray([0xA0, 0x1]))
        self.get_data()
        self.reloadSensors()
        self.signalButton.setText("Включить сирену" if self.currentData[-6] == 0 else "Выключить сирену")

    def onWindButtonClick(self):
        ser.write(bytearray([0xA1, 0x1]))
        self.get_data()
        self.reloadSensors()
        self.windButton.setText("Включить вентилятор" if self.currentData[-2] == 0 else "Выключить вентилятор")

    def ondoorButtonClick(self):
        if (self.currentData[-1] == 32):
            ser.write(bytearray([0xA2, 0x96]))
            self.doorButton.setText("Открыть дверь")
        else:
            ser.write(bytearray([0xA2, 0x20]))
            self.doorButton.setText("Закрыть дверь")

        self.get_data()

    def onMelodyButtonClick(self):
        ser.write(bytearray([0xA6, 0x1]))

    def get_data (self):
        sleep(0.1)
        _currentData = str(ser.read_all())
        _currentData = _currentData[2:_currentData.find('\\r\\n')]
        if (_currentData!=''):
            currentDataList = list(map(float, _currentData.split('|')))
            self.currentData = currentDataList
            print(currentDataList)

app = QApplication(sys.argv)
window = MainWindow()

window.show()
sys.exit(app.exec())


BOT_NAME = 'Cell'
SPIDER_MODULES = ['Cell.spiders']
NEWSPIDER_MODULE = 'Cell.spiders'

USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'

ROBOTSTXT_OBEY = False

# LOG_LEVEL = 'DEBUG'
# LOG_FILE = '../json/name.log'

# Configure maximum concurrent requests performed by Scrapy (default: 16)
CONCURRENT_REQUESTS = 16

DOWNLOAD_DELAY = 1
# The download delay setting will honor only one of:
# CONCURRENT_REQUESTS_PER_DOMAIN = 16
# CONCURRENT_REQUESTS_PER_IP = 16

# COOKIES_ENABLED = False

# Disable Telnet Console (enabled by default)
# TELNETCONSOLE_ENABLED = False

# Override the default request headers:
# DEFAULT_REQUEST_HEADERS = {
#   'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
#   'Accept-Language': 'en',
# }

# Enable or disable spider middlewares
# SPIDER_MIDDLEWARES = {
#    'Cell.middlewares.CellSpiderMiddleware': 543,
# }

# Enable or disable downloader middlewares
# DOWNLOADER_MIDDLEWARES = {
#    'Cell.middlewares.CellDownloaderMiddleware': 543,
# }

# Enable or disable extensions
# EXTENSIONS = {
#    'scrapy.extensions.telnet.TelnetConsole': None,
# }

ITEM_PIPELINES = {
    # 'Cell.pipelines.CellPipeline': 300,
    'Cell.pipelines.MongoDBPipeline': 301,
}

# Enable and configure the AutoThrottle extension (disabled by default)
# See https://doc.scrapy.org/en/latest/topics/autothrottle.html
# AUTOTHROTTLE_ENABLED = True
# The initial download delay
# AUTOTHROTTLE_START_DELAY = 5
# The maximum download delay to be set in case of high latencies
# AUTOTHROTTLE_MAX_DELfrom scrapy import loggingAY = 60
# The average number of requests Scrapy should be sending in parallel to
# each remote server
# AUTOTHROTTLE_TARGET_CONCURRENCY = 1.0
# Enable showing throttling stats for every response received:
# AUTOTHROTTLE_DEBUG = False

# Enable and configure HTTP caching (disabled by default)
# HTTPCACHE_ENABLED = True
# HTTPCACHE_EXPIRATION_SECS = 0
# HTTPCACHE_DIR = 'httpcache'
# HTTPCACHE_IGNORE_HTTP_CODES = [302,]
# HTTPCACHE_STORAGE = 'scrapy.extensions.httpcache.FilesystemCacheStorage'

COMMANDS_MODULE = 'Cell.commands'

MONGODB_SERVER = "124.42.117.168"
MONGODB_PORT = 27017
MONGODB_DB = "qisu"
MONGODB_COLLECTION = "iflow"


#!/usr/bin/env python
"""Create a reduced image of the detector readings from a Mantid workspace.

This reduces the detector readings for each pixel by integrating in the time
dimension.

"""
from __future__ import print_function
from __future__ import division

import string

import mantid.simpleapi

import plotly
import plotly.offline
import plotly.graph_objs

import numpy as np

import scipy.stats

TOF_TEMPLATE = '''
<button id="plotly-slice-decrement" type="button">[-]</button>
<input id="plotly-slice-range" type="range"></input>
<button id="plotly-slice-increment" type="button">[+]</button>
<script>
(function() {
var graphDivs = document.getElementsByClassName('plotly-graph-div');
var graphDiv = graphDivs[0];
var index = 0;

function changeSlice() {
  for (var i=0; i<graphDiv.data.length; ++i) {
    graphDiv.data[i].visible = false;
  }

  graphDiv.data[index].visible = true;

  Plotly.redraw(graphDiv);
}

var range = document.getElementById("plotly-slice-range");
range.style.marginTop = "20px";
range.style.width = "80%";
range.min = 0;
range.max = graphDiv.data.length - 1;
range.value = 0;
range.addEventListener('change', function(e) {
  index = +e.target.value;
  changeSlice();
});

var decrement = document.getElementById("plotly-slice-decrement");
decrement.addEventListener('click', function(e) {
  e.preventDefault();
  if (index > 0) {
    index--;
  }
  range.value = index;
  changeSlice();
});

var increment = document.getElementById("plotly-slice-increment");
increment.addEventListener('click', function(e) {
  e.preventDefault();
  if (index < graphDiv.data.length - 2) {
    index++;
  }
  range.value = index;
  changeSlice();
});

})();
</script>
'''

def restructure_histogram_data(det_lookup, data, bins=None):
    Y = []
    X = []
    Z = []
    for index, val in enumerate(data):
        (i, j, _) = det_lookup[index]
        X.append(j)
        Y.append(i)
        Z.append(val)
    Y = np.array(Y)
    X = np.array(X)
    Z = np.array(Z)

    det_width = len(np.unique(X))
    det_height = len(np.unique(Y))

    if bins is None:
        bins = [det_width // 2, det_height // 2]

    Zp, xedges, yedges, _ = scipy.stats.binned_statistic_2d(
        X, Y, Z,
        bins=bins,
        statistic='mean',
    )

    Xp = xedges[1:] - (xedges[1] - xedges[0]) / 2
    Yp = yedges[1:] - (yedges[1] - yedges[0]) / 2

    return Zp

def main(filename, outdir, output_type, include_plotly_js, plot_type, bin_width,
         num_bins):
    # Load the workspace
    workspace = mantid.simpleapi.Load(filename)
    run_number = workspace.getRunNumber()

    # Get the detector width and height from the workspace
    instrument = workspace.getInstrument()
    component = instrument[instrument.nelements() - 1]
    det_width = component.nelements()
    det_height = component[0][0].nelements()
    det_lookup = {
        component[i][0][j].getID(): component[i][0][j].getPos()
        for i in xrange(component.nelements())
        for j in xrange(component[i][0].nelements())
    }

    # Get the number of time units from workspace and calculate bin width
    blocksize = workspace.blocksize()
    if not bin_width:
        bin_width = blocksize // num_bins
    else:
        num_bins = blocksize // bin_width

    maximum = 0

    if plot_type == 'tof' or plot_type == 'both':
        # Rebin data
        rebinned_workspace = mantid.simpleapi.Rebin(
            workspace,
            Params='{},{},{}'.format(0, bin_width, bin_width * num_bins),
            FullBinsOnly=True,
        )

        rebinned_y = rebinned_workspace.extractY()
        maximum = max(maximum, np.log(np.max(rebinned_y)))

        all_rebinned = [
            restructure_histogram_data(det_lookup, rebinned_y[:, i])
            for i in range(num_bins)
        ]

    if plot_type == 'integrated' or plot_type == 'both':
        # Integrate along the time dimension to consolidate the data
        integration_workspace = mantid.simpleapi.Integration(workspace)

        # Get Y data
        integrated_y = integration_workspace.extractY()
        maximum = max(maximum, np.log(np.max(integrated_y)))

        # Restructure Y data
        integrated = restructure_histogram_data(det_lookup, integrated_y)

    rebinned_traces = []
    if plot_type == 'tof' or plot_type == 'both':
        for i, rebinned in enumerate(all_rebinned):
            # Mask out any values that will make taking the log difficult
            rebinned_z = rebinned
            rebinned_z = np.ma.masked_invalid(rebinned_z)
            mask = (0 < rebinned_z) & (rebinned_z < np.e)
            rebinned_z = np.ma.masked_where(mask, rebinned_z)
            rebinned_z = np.ma.log(rebinned_z)

            # Actually plot the data
            rebinned_trace = plotly.graph_objs.Heatmap(
                z=rebinned_z,
                zmax=maximum,
                visible=True if (i == 0) else 'legendonly',
                showlegend=True,
                name='Rebinned {}'.format(i),
            )

            rebinned_traces.append(rebinned_trace)

    import json
    import gzip
    with gzip.open('rebinned.json.gz', 'w') as f:
        json.dump([x.z.tolist() for x in rebinned_traces], f)

    integrated_traces = []
    if plot_type == 'integrated' or plot_type == 'both':
        # Mask out any values that will make taking the log difficult
        integrated_z = integrated
        integrated_z = np.ma.masked_invalid(integrated_z)
        mask = (0 < integrated_z) & (integrated_z < np.e)
        integrated_z = np.ma.masked_where(mask, integrated_z)
        integrated_z = np.ma.log(integrated_z)

        integrated_trace = plotly.graph_objs.Heatmap(
            z=Z,
            zmax=maximum,
        )

        integrated_traces.append(integrated_trace)

    layout = plotly.graph_objs.Layout(
        xaxis=dict(title='Tube'),
        yaxis=dict(title='Pixel'),
        showlegend=True,
    )

    print(len(integrated_traces + rebinned_traces))

    fig = plotly.graph_objs.Figure(
        data=integrated_traces + rebinned_traces,
        layout=layout,
    )

    # Save image to the disk
    output_filename = "EQSANS_{}_autoreduced.html".format(run_number)
    output_path = os.path.join(outdir, output_filename)

    if output_type == 'div':
        div = plotly.offline.plot(fig, output_type='div',
                                  include_plotlyjs=include_plotly_js)
        with open(output_path, 'w') as f:
            f.write(div)

    else: # output_type == 'file':
        plotly.offline.plot(fig, filename=output_path,
                            include_plotlyjs=include_plotly_js)

    if plot_type == 'tof' or plot_type == 'integrated':
        with open(output_path, 'a') as f:
            f.write(TOF_TEMPLATE)

if __name__ == "__main__":
    import argparse
    import os

    def path_exists(path):
        """Ensures that the paths provided by the user exist"""
        if not os.path.exists(path):
            raise argparse.ArgumentTypeError("{} does not exist".format(path))
        return path

    parser = argparse.ArgumentParser()
    parser.add_argument('filename', type=path_exists)
    parser.add_argument('outdir', type=path_exists)
    parser.add_argument('--output-type', choices=('div', 'file'), default='div')
    include_plotly_js = parser.add_mutually_exclusive_group(required=False)
    include_plotly_js.add_argument('--include-plotly-js',
                                   dest='include_plotly_js',
                                   action='store_true')
    include_plotly_js.add_argument('--no-include-plotly-js',
                                   dest='include_plotly_js',
                                   action='store_false')
    parser.set_defaults(include_plotly_js=True)
    parser.add_argument('--plot-type', choices=('integrated', 'tof', 'both'),
                        default='integrated')
    parser.add_argument('--bin-width', type=int, default=None)
    parser.add_argument('--num-bins', type=int, default=1)
    args = parser.parse_args()

    main(**vars(args))


import sys
divisors = 0
start = 10000

def factorize(n):
    total = 0
    for i in range(1, n+1):
        if n % i == 0:
            total += 1
    return total

while divisors < 501:
    triangleNumber = 0
    start += 1

    for i in range(1, start):
        triangleNumber += i
    divisors = factorize(triangleNumber)
    print("the number " + str(triangleNumber) +
          " has " + str(divisors) + " divisors.")


def merge_dict(d1: dict[object, int], d2: dict[object, int]) -> None:
    '''
    Add key/value pairs from d2 into d1. If a key from d2 already
    appears in d1, the new value in d1 is the sum of the values. If a
    key appears only in d1 or d2, then the new value in d1 is the
    original value from the dictionary that contained this key.
    d2 is unchanged.
    >>> d1 = {5: 3, 4: 2}
    >>> d2 = {4: 7, 6: 3}
    >>> merge_dict(d1, d2)
    >>> d1 == {4: 9, 5: 3, 6: 3}
    True
    '''
    for key in d2:
        if key in d1:
            d1[key] = d1[key] + d2[key]
        else:
            d1[key] = d2[key]


#약수 구하기

num = int(input("1이상의 숫자를 입력: "))

divisors = []
t_num = int(num/2)  #약수는 자기 자신을 반을 나눈것을 넘지 않는다. 홀수를 대비해 int로 소수점 없앤다.

while t_num > 1:  #t_num을 1씩 감소시키면서 나누어떨어지는지 확인
    if num % t_num == 0:
        divisors.append(t_num)
    t_num -= 1

print(divisors)


import pika
import json
import time
import os
import logging

import django
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
django.setup()

from users.models import User, Notification, NotificationInfo
from feedback.models import Playlist
from config import settings
from podcast.models import Podcast
from main.utils import authentication_log_format, rss_log_format

logger = logging.getLogger('elastic-logger')

def login_callback(chanel, method, properties, body):
    try:
        data = json.loads(body)
        user = User.objects.get(username=data['username'])
        notification_info = NotificationInfo.objects.create(message=data['message'])
        Notification.objects.create(user = user, message = notification_info)
        log_data = authentication_log_format(user,data)
        logger.info(json.dumps(log_data))

    except Exception as error:
        log_data = authentication_log_format(user, data, error)
        logger.error(json.dumps(log_data))

def login_consume():
    connection = pika.BlockingConnection(pika.ConnectionParameters(host=settings.RABBITMQ_HOST))
    chanel = connection.channel()

    chanel.queue_declare(queue='login')
    chanel.basic_consume(queue='login', on_message_callback=login_callback)

    chanel.start_consuming()

def register_callback(chanel, method, properties, body):
    try:
        data = json.loads(body)
        user = User.objects.get(username=data['username'])
        notification_info = NotificationInfo.objects.create(message=data['message'])
        Notification.objects.create(user = user, message = notification_info)
        log_data = authentication_log_format(user,data)
        logger.info(json.dumps(log_data))
    except Exception as error:
        log_data = authentication_log_format(user, data, error)
        logger.error(json.dumps(log_data))

def register_consume():
    connection = pika.BlockingConnection(pika.ConnectionParameters(host=settings.RABBITMQ_HOST))
    chanel = connection.channel()

    chanel.queue_declare(queue='register')
    chanel.basic_consume(queue='register', on_message_callback=login_callback)

    chanel.start_consuming()

def update_podcast_callback(chanel, method, properties, body):
    try:
        data = json.loads(body)
        playlists = Podcast.objects.get(id=data['podcast']).playlist_set.all()
        for playlist in playlists:
                    notification = NotificationInfo.objects.create(message = data['message'])
                    user = User.objects.get(id=playlist.account.id)
                    Notification.objects.create(user = user, message = notification)
        log_data = rss_log_format(data)
        logger.info(json.dumps(log_data))
    except Exception as error:
        log_data = rss_log_format(data, error)
        logger.error(json.dumps(log_data))

def update_podcast_consume():
    connection = pika.BlockingConnection(pika.ConnectionParameters(host=settings.RABBITMQ_HOST))
    chanel = connection.channel()

    chanel.queue_declare(queue='update_podcast')

    chanel.basic_consume(queue='update_podcast', on_message_callback=update_podcast_callback)

    chanel.start_consuming()


import os
import re
from collections import deque
from gi import require_version
from gi.repository import Gtk
from gi.repository.GLib import timeout_add, source_remove, idle_add, unix_signal_add, PRIORITY_HIGH
require_version('AppIndicator3', '0.1')
from gi.repository import AppIndicator3 as appIndicator

from cpulib.run import run, run_nowait
from cpulib.config import config

def get_cpu_jiffies():
    result = run("grep 'cpu ' /proc/stat", shell=True)
    splitted = re.split(' +', result)
    assert splitted[0] == 'cpu'
    return list(map(int, splitted[1:5]))

def get_cpu_usage(hist):
    first = hist[0]
    second = hist[-1]
    used = second[0] + second[1] + second[2] - first[0] - first[1] - first[2]
    total = used + second[3] - first[3]
    if not total:
        return 0
    return 100 * used / total

class TaskBarIcon():
    def __init__(self):
        self.cur_icon = ''
        self.ind = appIndicator.Indicator.new(
            "CpuIndicator",
            os.path.abspath("img/unknown.png"),
            appIndicator.IndicatorCategory.APPLICATION_STATUS)
        self.ind.set_status(appIndicator.IndicatorStatus.ACTIVE)
        self.create_menu()
        self.ind.set_menu(self.menu)

        self.hist = deque()

        timeout_add(config['GUI_MS_BETWEEN_REDRAWS'], self.update)

    def update(self):
        self.update_icon()
        return True

    def update_icon(self):
        self.hist.append(get_cpu_jiffies())
        if len(self.hist) > config['SMOOTH_CYCLES']:
            self.hist.popleft()
        percent = get_cpu_usage(self.hist)
        if percent < 10:
            rounded = int(percent) + 1
        else:
            rounded = int((percent // 10 + 1) * 10)
        if rounded > 100:
            rounded = 100

        self.set_icon(rounded)

    def set_icon(self, percent):
        full_path = 'img/red-percent-' + str(percent) + '.png'
        if self.cur_icon == full_path:
            return
        self.cur_icon = os.path.abspath(full_path)

        self.ind.set_icon_full(self.cur_icon, '')

    def create_menu(self):
        self.menu = Gtk.Menu()

        self.menu.monitor = Gtk.MenuItem(label='Open System monitor')
        self.menu.monitor.connect("activate", self.on_monitor)
        self.menu.append(self.menu.monitor)

        self.menu.append(Gtk.SeparatorMenuItem.new())

        self.menu.exit = Gtk.MenuItem(label='Exit CPU indicator')
        self.menu.exit.connect("activate", self.on_exit)
        self.menu.append(self.menu.exit)

        self.menu.show_all()

    def on_monitor(self, widget):
        run_nowait('gnome-system-monitor', shell=True)

    def on_exit(self, widget):
        self.exit()

    def exit(self):
        Gtk.main_quit()


from tokenizers import ByteLevelBPETokenizer

tokenizer = ByteLevelBPETokenizer('vocab/vocab.json', 'vocab/merges.txt')

tokenizer.enable_truncation(max_length=512)

token_text = tokenizer.encode("<number> hdG jRGd JYGWj GdehGO GdGajhfjI, dG SjeG aj Tcd GdgjQhjf, jJSHH aj eYXe WdH YdGL JYGWj GdeNOQGJ aj eYXe HdOGf hSW hTQb hLfhH TQb GSjG.")
print(token_text)

print("done")


def specialArray(nums):

    # Sort the given array
    nums.sort()

    n = len(nums)

    # Now, for each value of x, we just need to find the smallest number that is >= x
    # Once we find that, all numbers after that number are already >= x as array is sorted

    for x in range(n + 1):

        # Binary Search
        start = 0
        end = n - 1
        result = -1

        while start <= end:
            mid = start + (end - start) // 2
            if nums[mid] >= x:
                result = mid
                end = mid - 1
            else:
                start = mid + 1

        if result >= 0 and n - result == x: return x

    # If not a special array
    return -1

nums = [0,4,3,0,4]

print("Output ->", specialArray(nums))

007. Special Array With X Elements Greater Than or Equal X/BinarySearch.py


from PyQt5 import QtCore, QtWidgets, Qt, uic
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *

import sys
from pb_Woo_Order_Class import PbWooCommerce
from cls_web_order import webOrderUI
from cls_stock_levels import stockUI
import fnc_meta_processing
import dialog_functions
import delivery_note_printing

# Setup Logging
# logger.debug('My message with %s', 'variable data')
import logging
logger = logging.getLogger(__name__)

#Set some column constants
COL_READY_DATE = 4
COL_COMPLETE = 7

class worker_load_orders(QObject):
        finished = pyqtSignal(list)

        @pyqtSlot()  #Wrap in slot for better communication etc
        def run(self):
            #Get the Orders from Woocommerce
            wc = PbWooCommerce()
            myorders = wc.get_orders('packing, processing')
            logger.debug('Orders Loaded')
            self.finished.emit(myorders)

class appUI(QtWidgets.QMainWindow):
    load_orders_requested = pyqtSignal()

    def __init__(self):
        super(appUI, self).__init__() # Call the inherited classes __init__ method
        uic.loadUi('ui_main_window.ui', self) # Load the .ui file
        self.logger = logging.getLogger(__name__)
        self.logger.info('Loading Orders window')
        self.lblStatus.setStyleSheet('color:#EE1C25')

        # Set Column Widths
        self.orderstableWidget.setColumnWidth(0,150)
        self.orderstableWidget.setColumnWidth(1, 320)
        self.orderstableWidget.setColumnWidth(2,150)
        self.orderstableWidget.setColumnWidth(5,122)
        self.orderstableWidget.setColumnWidth(6,145)
        self.orderstableWidget.setColumnWidth(7,145)

        self.show()  # Show the GUI

        self.load_orders()

        #Add connections to slots
        self.btnRefreshOrders.clicked.connect(self.refresh_orders)
        self.actionRefresh_Pricing.triggered.connect(self.refreshPricesOffsite)
        self.actionCheck_Stock.triggered.connect(self.checkStock)

    def load_orders(self):
        # Create a worker object and a thread
        self.btnRefreshOrders.hide()
        logger.debug("Getting Orders from the Website")
        self.lblStatus.setText("Getting Orders from Website")
        self.statusBar().showMessage("Getting Orders from Website")
        self.worker = worker_load_orders()
        self.thread = QThread()
        self.worker.moveToThread(self.thread)

        self.worker.finished.connect(self.process_orders)
        self.load_orders_requested.connect(self.worker.run)
        #We are killing the thread here - vs I think it also possible to keep alive and trigger as well
        self.worker.finished.connect(self.thread.quit)
        self.worker.finished.connect(self.worker.deleteLater)
        self.thread.finished.connect(self.thread.deleteLater)

        # Assign the worker to the thread and start the thread

        self.thread.start()

        # Start the load by emitting a signal
        self.load_orders_requested.emit()

    def process_orders(self, myorders):
        #Process the orders once the thread completes
        self.orderstableWidget.setRowCount(len(myorders))
        rowindex=0
        for row in myorders:
            order_id = QTableWidgetItem(str(row['id']))
            logger.debug("Loading order {0}".format(row['id']))
            order_id.setFlags(order_id.flags() & ~ Qt.ItemIsEditable)
            self.orderstableWidget.setItem(rowindex,0, order_id)

            delivery_data = fnc_meta_processing.parse_order_meta_data(row)
            if delivery_data[0] == 'pickup':
                if delivery_data[3]: #Check in case no date was in the order
                    ready_by_date = delivery_data[3].strftime("%d/%m/%Y")
            else:
                if delivery_data[1]:
                    ready_by_date = delivery_data[1].strftime("%d/%m/%Y")

            self.orderstableWidget.setItem(rowindex,1, QTableWidgetItem(str(row['billing']['first_name'] + ' ' + row['billing']['last_name'])))
            if row['status'] == 'processing':
                self.orderstableWidget.setItem(rowindex, 2, QTableWidgetItem('Ready for Delivery'))
                delivery_button = QtWidgets.QPushButton('Print Delivery Slip')
                delivery_button.setStyleSheet("background-color : #89CFF0")
                delivery_button.clicked.connect(self.print_delivery_note)
                self.orderstableWidget.setCellWidget(rowindex, 6, delivery_button)
                complete_button = QtWidgets.QPushButton('Finalise Order')
                complete_button.setStyleSheet("background-color : #8d6852")
                complete_button.clicked.connect(self.complete_order)
                self.orderstableWidget.setCellWidget(rowindex, 7, complete_button)

            else:
                self.orderstableWidget.setItem(rowindex, 2, QTableWidgetItem(row['status'].capitalize()))

            self.orderstableWidget.setItem(rowindex,3, QTableWidgetItem(delivery_data[0].capitalize()))
            self.orderstableWidget.setItem(rowindex, COL_READY_DATE, QTableWidgetItem(ready_by_date))

            #Add Edit Button
            # create an cell widget
            if row['status'] == 'packing':
                btn = QtWidgets.QPushButton('Edit Order')
                btn.setStyleSheet("background-color : #27ee1c")
            else:
                btn = QtWidgets.QPushButton('View Order')
                btn.setStyleSheet("background-color : #EE1C25 ;"
                                  "color: white")

            #https://stackoverflow.com/questions/47621172/applying-styles-to-pyqt-widgets-from-external-stylesheet
            btn.clicked.connect(self.orderClicked)
            self.orderstableWidget.setCellWidget(rowindex, 5, btn)
            rowindex +=1

        #Sort the table to oldest orders are first.
        self.orderstableWidget.sortItems(COL_READY_DATE, QtCore.Qt.AscendingOrder)

        self.btnRefreshOrders.show()
        self.statusBar().showMessage("Ready")
        self.lblStatus.setText("Ready")

    @QtCore.pyqtSlot()
    def orderClicked(self):
        button = self.sender()
        if button:
            row = self.orderstableWidget.indexAt(button.pos()).row()
            orderNumber = self.orderstableWidget.item(row, 0).text()
            self.dialog = webOrderUI(orderNumber)
            self.dialog.show()

    @QtCore.pyqtSlot()
    def checkStock(self):
        #Open the Stock Window
        self.dialog = stockUI()
        self.dialog.show()

    @QtCore.pyqtSlot()
    def refresh_orders(self):
        #refresh the orders list
        print("Refreshing Orders")
        self.statusBar().showMessage("Getting Orders from Website")
        self.orderstableWidget.setRowCount(0)
        self.load_orders()

    def refreshPricesOffsite(self):
        print('Call to refresh prices of site to Manticore')
        fnc_meta_processing.webhook_update_prices()
        dialog_functions.show_information_dialog("Request has been sent.")

    def print_delivery_note(self):
        #Print a delivery note to PrintNode
        button = self.sender()
        if button:
            row = self.orderstableWidget.indexAt(button.pos()).row()
            orderNumber = self.orderstableWidget.item(row, 0).text()
            delivery_note_printing.create_delivery(orderNumber)

    def complete_order(self):
        #Update the order to have status of completed
        button = self.sender()
        if button:
            row = self.orderstableWidget.indexAt(button.pos()).row()
            orderNumber = self.orderstableWidget.item(row, 0).text()
            logger.info('Completing Order %s', orderNumber)
            updated_order = {'status': 'completed'}
            self.wc = PbWooCommerce()
            result = self.wc.update_order(updated_order, orderNumber)
            dd = dialog_functions.show_information_dialog("The order has been finalised and customer will be charged")
            self.refresh_orders

if __name__ == '__main__':
    # Get list of Orders being packed from
    #logger.info("Start Connection to Woo Commerce")
    #This is make the class a global so we clean up the others where is a defined in the class for final integration
    wc = PbWooCommerce()
    app = QtWidgets.QApplication(sys.argv)
    window = appUI()
    app.exec_()


import csv

with open('C:\\Users\\Burto\\Downloads\\GO-databases DEDS-week 4 & 5\\HC code\\Week 9\\BolSentiment.csv', newline='', encoding='utf-8') as infile, open('reviews_fixed.csv', mode='w', newline='', encoding='utf-8') as outfile:
    reader = csv.reader(infile, delimiter=';')
    writer = csv.writer(outfile, delimiter=';')

    # Write headers
    headers = next(reader)
    headers.append('first_5_words')
    writer.writerow(headers)

    # Write rows
    for row in reader:
        if len(row) >= 2:
            review = row[1]
            first_5_words = " ".join(review.split()[:5])
            inhoud = " ".join(review.split()[5:])
            row[1] = inhoud
            row.append(first_5_words)
            writer.writerow(row)

print('Done')


def compress(s, txt_len):
    words = []
    for i in range(0, len(s), txt_len):
        words.append(s[i: i+txt_len])

    words += [""]
    ret = ""

    cmp = words[0]

    cnt = 1
    for word in words[1:]:
        if cmp == word:
            cnt += 1
        else:
            ret += str(cnt) if cnt > 1 else ""
            ret += cmp
            cmp = word
            cnt = 1

    return len(ret)

def solution(s):
    answer = len(s)
    for txt_len in range(1, len(s)//2+1):
        answer = min(answer, compress(s, txt_len))
    return answer

if __name__ == "__main__":
    s = "aabbaccc"
    print(solution(s))


#Program to find the position of minimum and maximum elements of a list.
list1=input("Enter the list of elements:").split()
list=[int(i) for i in list1]
min=list[0]
max=list[0]
i=1
while i<len(list):
    if list[i]>=max:
        max=list[i]
        max1=i
    if list[i]<=min:
        min=list[i]
        min1=i
    i+=1
print("The position of maximum elements in the list",list,"is:",max1)
print("The position of minimum elements in the list",list,"is:",min1)


import cv2 as cv

img =cv.imread('photos/dog.jpg')
img =cv.resize(img, (400,250))
cv.imshow('Dog', img)

gray = cv.cvtColor(img, cv.COLOR_RGB2GRAY)
cv.imshow('Gray', gray)

#Simple Thresholding
threshold, thresh = cv.threshold(gray, 150, 255, cv.THRESH_BINARY)
cv.imshow('Thresholded Simple', thresh)

#Simle thersholding Inversed
threshold, thresh_inv = cv.threshold(gray, 150, 255, cv.THRESH_BINARY_INV)
cv.imshow('Thresholded Simple-Inverse', thresh_inv)

#Adaptive Thresholding
adaptive_thres = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 11, 3)
cv.imshow('Adaptive Threshold', adaptive_thres)

#Adaptive Thresholding Inversed
adaptive_thres_inv = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY_INV, 11, 3)
cv.imshow('Adaptive Threshold-Inversed', adaptive_thres_inv)
cv.waitKey(0)


import math
import logging
from functools import partial
from collections import OrderedDict

import torch
import torch.nn as nn
import torch.nn.functional as F
from timm.data import IMAGENET_DEFAULT_MEAN, IMAGENET_DEFAULT_STD
# from .layers import StdConv2dSame, DropPath, to_2tuple, trunc_normal_
from timm.models.layers import DropPath, to_2tuple, trunc_normal_
from timm.models.vision_transformer import DropPath, Mlp
from transformers.models.bert.modeling_bert import BertSelfAttention
_logger = logging.getLogger(__name__)

class Mlp(nn.Module):
    def __init__(self, in_features, hidden_features=None, out_features=None, act_layer=nn.GELU, drop=0.):
        super().__init__()
        out_features = out_features or in_features
        hidden_features = hidden_features or in_features
        self.fc1 = nn.Linear(in_features, hidden_features)
        self.act = act_layer()
        self.fc2 = nn.Linear(hidden_features, out_features)
        self.drop = nn.Dropout(drop)

    def forward(self, x):
        x = self.fc1(x)
        x = self.act(x)
        x = self.drop(x)
        x = self.fc2(x)
        x = self.drop(x)
        return x

class Attention(nn.Module):
    def __init__(self, dim, num_heads=8, qkv_bias=False, qk_scale=None, attn_drop=0., proj_drop=0.):
        super().__init__()
        self.num_heads = num_heads
        head_dim = dim // num_heads
        # NOTE scale factor was wrong in my original version, can set manually to be compat with prev weights
        self.scale = qk_scale or head_dim ** -0.5

        self.qkv = nn.Linear(dim, dim * 3, bias=qkv_bias)
        self.attn_drop = nn.Dropout(attn_drop)
        self.proj = nn.Linear(dim, dim)
        self.proj_drop = nn.Dropout(proj_drop)

    def forward(self, x, attention_mask=None):
        B, N, C = x.shape
        qkv = self.qkv(x).reshape(B, N, 3, self.num_heads, C // self.num_heads).permute(2, 0, 3, 1, 4)
        q, k, v = qkv[0], qkv[1], qkv[2]   # make torchscript happy (cannot use tensor as tuple)

        attn = (q @ k.transpose(-2, -1)) * self.scale
        if attention_mask is not None:
            attn = attn + attention_mask
        attn = attn.softmax(dim=-1)
        attn = self.attn_drop(attn)

        x = (attn @ v).transpose(1, 2).reshape(B, N, C)
        x = self.proj(x)
        x = self.proj_drop(x)
        return x

class Block(nn.Module):

    def __init__(self, dim, num_heads, mlp_ratio=4., qkv_bias=False, qk_scale=None, drop=0., attn_drop=0.,
                 drop_path=0., act_layer=nn.GELU, norm_layer=nn.LayerNorm):
        super().__init__()
        self.norm1 = norm_layer(dim)
        self.attn = Attention(
            dim, num_heads=num_heads, qkv_bias=qkv_bias, qk_scale=qk_scale, attn_drop=attn_drop, proj_drop=drop)
        # NOTE: drop path for stochastic depth, we shall see if this is better than dropout here
        self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()
        self.norm2 = norm_layer(dim)
        mlp_hidden_dim = int(dim * mlp_ratio)
        self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)

    def get_extended_attention_mask(self, attention_mask, input_shape):
        if attention_mask.dim() == 3:
            extended_attention_mask = attention_mask[:, None, :, :]
        elif attention_mask.dim() == 2:

            extended_attention_mask = attention_mask[:, None, None, :]
        else:
            raise ValueError(
                f"Wrong shape for input_ids (shape {input_shape}) or attention_mask (shape {attention_mask.shape})"
            )
        extended_attention_mask = extended_attention_mask  # fp16 compatibility
        extended_attention_mask = (1.0 - extended_attention_mask) * -10000.0
        return extended_attention_mask

    def forward(self, x, attn_mask=None):
        if attn_mask is not None:
            attn_mask = self.get_extended_attention_mask(attn_mask, x.shape)
        x = x + self.drop_path(self.attn(self.norm1(x), attn_mask))
        x = x + self.drop_path(self.mlp(self.norm2(x)))
        return x

class BertAttention(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.self = BertSelfAttention(config)
        self.dense = nn.Linear(config.hidden_size, config.hidden_size)
        self.dropout = nn.Dropout(config.hidden_dropout_prob)

    def forward(
        self,
        hidden_states,
        attention_mask=None,
        encoder_hidden_states=None,
        encoder_attention_mask=None,
    ):
        self_outputs = self.self(
            hidden_states=hidden_states,
            attention_mask=attention_mask,
            encoder_hidden_states=encoder_hidden_states,
            encoder_attention_mask=encoder_attention_mask,
        )
        attention_output = self.dense(self_outputs[0])
        attention_output = self.dropout(attention_output) + hidden_states

        return attention_output

class TransformerCrossAttnLayer(nn.Module):
    def __init__(self, config):
        super().__init__()
        self.norm1 = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
        self.attention = BertAttention(config)

        self.cross_norm = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
        self.crossattention = BertAttention(config)

        self.norm2 = nn.LayerNorm(config.hidden_size, eps=config.layer_norm_eps)
        self.mlp = Mlp(in_features=config.hidden_size, hidden_features=config.hidden_size*4, out_features=config.hidden_size)

    def get_extended_attention_mask(self, attention_mask):
        if attention_mask.dim() == 3:
            extended_attention_mask = attention_mask[:, None, :, :]
        elif attention_mask.dim() == 2:
            extended_attention_mask = attention_mask[:, None, None, :]
        else:
            raise ValueError
        extended_attention_mask = extended_attention_mask  # fp16 compatibility
        extended_attention_mask = (1.0 - extended_attention_mask) * -10000.0
        return extended_attention_mask

    def forward(
        self,
        hidden_states,
        attention_mask=None,
        encoder_hidden_states=None,
        encoder_attention_mask=None,
    ):
        attention_mask = self.get_extended_attention_mask(attention_mask) if attention_mask is not None else None
        encoder_attention_mask = self.get_extended_attention_mask(encoder_attention_mask) if encoder_attention_mask is not None else None

        hidden_states = self.norm1(hidden_states)
        attention_output = self.attention(hidden_states, attention_mask)

        attention_output = self.cross_norm(attention_output)
        attention_output = self.crossattention(
            attention_output,
            attention_mask,
            encoder_hidden_states,
            encoder_attention_mask,
        )

        attention_output = self.norm2(attention_output)
        layer_output = self.mlp(attention_output)
        layer_output += attention_output

        return layer_output


# -*- coding: utf-8 -*-
from ..report.service import ReportService
from .models import Wsp as wsp_model
from graphqlapp.utils import extract_value_from_input

class WspService(object):

    def getWspById(self, input):
        wsp = extract_value_from_input(
            input=input,
            field_id='id',
            model_type='Wsp',
            model=wsp_model
        )

        return wsp

    def getWspListByDict(self, param=None):
        return wsp_model.objects.filter(
            **param
        )

    def getAllWspBySampleType(self, type_list):
        kwargs = {}
        for t in type_list:
            kwargs[t] = True
        return wsp_model.objects.dynamic_or(
            **kwargs
        )

    def getAllWspBySampleTypeAndStructType(self, type_list, struct_type):
        kwargs = {}
        for t in type_list:
            kwargs[t] = True
        return wsp_model.objects.dynamic_or(
            **kwargs
        ).filter(structure__struct_type__value=struct_type)

    def NextReviewDate(self, wsp):
        # tutti i report di un wsp ordinati per sampling_date
        reportService = ReportService()

        param = {'wsp': wsp}
        reportList = reportService.getReportListByDict(param, '-sampling_date')

        review_date = None
        if reportList:
            if reportList[0].review_date:
                review_date = str(
                    reportList[0].review_date.month
                ) + "/" + str(reportList[0].review_date.year)
            else:
                review_date = "-"

        return review_date

    def AlertLevel(self, wsp):
        # valore peggiore di legionella dell'ultimo rap fatto su questo wsp
        reportService = ReportService()
        values = ['cold_ufcl', 'cold_flow_ufcl', 'hot_ufcl', 'hot_flow_ufcl']

        # tutti i report di un wsp ordinati per sampling_date
        param = {'wsp': wsp}
        reportList = reportService.getReportListByDict(param, '-sampling_date')

        if reportList:

            worst_level = 4
            worst_label = ""

            range_ufcl = reportList[0].rangesettings.ufcl

            for val in values:
                if range_ufcl:
                    for ran in range_ufcl:
                        if 'priority' in ran.keys():
                            if 'from' in ran.keys() and 'to' in ran.keys():
                                if getattr(reportList[0], val) >= ran['from']:
                                    if getattr(
                                            reportList[0], val) <= ran['to']:
                                        if ran['priority'] < worst_level:
                                            worst_level = ran['priority']
                                            worst_label = ran['level']
                            elif (
                                'from' in ran.keys() and
                                'to' not in ran.keys()
                            ):
                                if getattr(reportList[0], val) >= ran['from']:
                                    if ran['priority'] < worst_level:
                                        worst_level = ran['priority']
                                        worst_label = ran['level']
                            else:
                                if getattr(reportList[0], val) <= ran['to']:
                                    if ran['priority'] < worst_level:
                                        worst_level = ran['priority']
                                        worst_label = ran['level']
        else:
            worst_label = 'not assigned'

        return worst_label

    def Actions(self):
        # recupero le stesse azioni che sono prosenti del dettaglio del WSP
        # TODO
        pass


# Imagine you are designing a banking application. What would a
# customer look like? What attributes would she have? What methods
# would she have?
class banking_app:
    def __init__(self,accountname,accountnumber,address,phonenumber,fathersname,mothersname,balance,interestaccured,loan):
        self.accountname=accountname
        self.accountnumber=accountnumber
        self.address=address
        self.phonenumber=phonenumber
        self.fathersname=fathersname
        self.mothersname=mothersname
        self.balance=balance
        self.interestaccured=interestaccured
        self.loan=loan

    def displaybalance(self):
        return self.balance

    def displaydetails(self):
        return self.accountname, self.accountnumber, self.address, self.phonenumber

    def deposit(self,amount):
        self.balance=self.balance+amount
        print("Your balance is %d"%(self.balance))

    def withdraw(self,amount):
        if int(self.balance)>amount:
            self.balance=int(self.balance)-amount
            print("You've withdrawn %d amount"%(amount))
            print("Your available balance is %d"%(self.balance))
        else:
            print("The withdraw amount is less than the available balance")

c1=banking_app('Hari Adhikari','00148914841994','Chitwan','9845012345','Shyam Adhikari','Gita Adhikari','74881','375','0')
print(c1.displaydetails())
print(c1.displaybalance())
c1.withdraw(20000)
c1.deposit(10000)


from dataclasses import dataclass
from typing import List, Optional

from neoclient import Service, base_url, get

@dataclass
class Repository:
    id: int
    name: str
    description: Optional[str]

@base_url("https://api.github.com/")
class GitHub(Service):
    @get("users/{user}/repos")
    def list_repos(self, user: str) -> List[Repository]:
        ...

service: GitHub = GitHub()

repositories: List[Repository] = service.list_repos("octocat")

repository: Repository
for repository in repositories:
    print(repository)


import os
from PIL import Image
import numpy as np

bs_dir = '/mnt/lustre/fnzhan/datasets/CVPR2022/night2day/'
sv_dir = bs_dir + 'split/test/'

im_dir = bs_dir + 'test/'

nms = os.listdir(im_dir)
# n = 0
for nm in nms:
    im_path = im_dir + nm
    im = Image.open(im_path)
    im = np.array(im)
    inp, gt = im[:, 0:256, :], im[:, 256:, :]
    inp, gt = Image.fromarray(inp), Image.fromarray(gt)
    inp.save(sv_dir + 'input/' + nm)
    gt.save(sv_dir + 'gt/' + nm)


from aiounittest import AsyncTestCase
from aiounittest.mock import AsyncMockIterator
from unittest.mock import Mock

async def fetch_some_text(source):
    res = ''
    async for txt in source.paginate():
        res += txt
    return res

class MyAsyncMockIteratorTest(AsyncTestCase):

    async def test_add(self):
        source = Mock()
        mock_iter = AsyncMockIterator([
            'asdf', 'qwer', 'zxcv'
        ])
        source.paginate.return_value = mock_iter

        res = await fetch_some_text(source)
        self.assertEqual(res, 'asdfqwerzxcv')
        mock_iter.assertFullyConsumed()
        mock_iter.assertIterCount(3)


"""
Train dataloader
"""
from data.base_dataset import BaseDataset
import os
import glob
import pandas as pd
import numpy as np
import nibabel as nib
import torch
from util.util import seg_body, mkdir

class TrainDataset(BaseDataset):
    """A Train dataset class for training model."""
    @staticmethod
    def modify_commandline_options(parser, is_train):
        """Add new dataset-specific options, and rewrite default values for existing options.

        Parameters:
            parser          -- original option parser
            is_train (bool) -- whether training phase or test phase. You can use this flag to add training-specific or test-specific options.

        Returns:
            the modified parser.
        """
        return parser

    def __init__(self, opt):
        """Initialize this dataset class.

        Parameters:
            opt (Option class) -- stores all the experiment flags; needs to be a subclass of BaseOptions

        A few things can be done here.
        - save the options (have been done in BaseDataset)
        - get image paths and meta information of the dataset.
        """
        # save the option and dataset root
        BaseDataset.__init__(self, opt)

        self.rootdir = opt.dataroot
        self.isTrain = opt.isTrain

        self.input_paths = sorted(glob.glob(self.rootdir + '/imagesTr/input/*.nii.gz'))  # get image paths
        self.target_paths = sorted(glob.glob(self.rootdir + '/imagesTr/target/*.nii.gz'))  # get image paths

    def __getitem__(self, idx):
        """Return a data point and its metadata information.

        Parameters:
            index -- a random integer for data indexing

        Returns:
            a dictionary of data with their names. It usually contains the data itself and its metadata information.

        Step 1: get a random image path: e.g., path = self.image_paths[index]
        Step 2: load your data from the disk with nibabel, clip between [-1000:1000] and normalize [-1:1]
        Step 3: convert your data to a PyTorch tensor.
        Step 4: return a data point as a dictionary.
        """
        # Image A ------------------------------------------------
        # read a image given a random integer index
        filepath_A = self.input_paths[idx]
        name_A = os.path.basename(filepath_A)
        # print("filepath_A", filepath_A)

        # Read input image
        nifti_A = nib.load(filepath_A)
        spacing = nifti_A.header.get_zooms()
        img_A = nifti_A.get_fdata()
        img_arr_A = img_A.clip(-1000,1000)
        img_arr_A = (img_arr_A-img_arr_A.min())/(img_arr_A.max()-img_arr_A.min())*2-1

        if self.isTrain:
            # Get body of the input
            maskpath_A = self.rootdir + '/imagesTr/input/body/' + name_A
            if not os.path.isfile(maskpath_A):
                # Body Segmentation of input
                mask_arr_A = seg_body(img_A)

                # Save segmentation to avoid resegmentation and reduce time
                if not os.path.isdir(self.rootdir + '/imagesTr/input/body/'):
                    mkdir(self.rootdir + '/imagesTr/input/body/')
                nib.save(nib.Nifti1Image(mask_arr_A, nifti_A.affine, nifti_A.header), maskpath_A)
            else:
                mask_arr_A = nib.load(maskpath_A).get_fdata()

            # Image B ------------------------------------------------
            tmp = name_A.rsplit('_',1)[0] # Get the image case number
            ftmp = [s for s in self.target_paths if tmp in s and name_A not in s]

            # Get the target path
            idx_rd = np.random.randint(0,len(ftmp))
            filepath_B = ftmp[idx_rd] # Get a random index value from the same case
            name_B = os.path.basename(filepath_B)
            maskpath_B = self.rootdir + '/imagesTr/target/body/' + name_B
            # print("filepath_B", filepath_B)

            # Read target image
            nifti_B = nib.load(filepath_B)
            img_B = nifti_B.get_fdata()
            img_arr_B = img_B.clip(-1000, 1000)
            img_arr_B = (img_arr_B-img_arr_B.min())/(img_arr_B.max()-img_arr_B.min())*2-1

            # Get body of the target
            if not os.path.isfile(maskpath_B):
                # Body Segmentation of input
                mask_arr_B = seg_body(img_B)

                # Save segmentation to avoid resegmentation and reduce time
                if not os.path.isdir(self.rootdir + '/imagesTr/target/body/'):
                    mkdir(self.rootdir + '/imagesTr/target/body/')
                nib.save(nib.Nifti1Image(mask_arr_B, nifti_B.affine, nifti_B.header), maskpath_B)
            else:
                mask_arr_B = nib.load(maskpath_B).get_fdata()

            # Dvf A to B ------------------------------------
            # NOTES: DVF are obtained with the ptvreg algorithm
            dvf_nii = nib.load(self.rootdir + '/imagesTr/target/dvf/' + name_B)
            dvf_arr = dvf_nii.get_fdata().transpose(3,0,1,2) # change 4th channels to C for Tensor
            dvf_arr[0, ...] = dvf_arr[0, ...] / spacing[0]
            dvf_arr[1, ...] = dvf_arr[1, ...] / spacing[1]
            dvf_arr[2, ...] = dvf_arr[2, ...] / spacing[2]
            dvf = torch.from_numpy(dvf_arr.astype(np.float32))

        # Convert to torch
        img_A = torch.from_numpy(img_arr_A.astype(np.float32))
        img_B = torch.from_numpy(img_arr_B.astype(np.float32))

        # Calculate alpha
        dif = np.where(mask_arr_A == mask_arr_B, 0, 1)
        dif[:,dif.shape[1]//2:,:] = 0 # Keep only the anterior part (the back doesn't matter)

        # Distance
        alpha = np.array([np.mean(np.sum(dif, axis = 1))*spacing[1]])
        # print('alpha', alpha)

        return {'image_A': img_A, 'fpath_A': filepath_A,
                'image_B': img_B, 'fpath_B': filepath_B,
                'alpha': alpha,
                'dvf' : dvf
               }

    def __len__(self):
        """Return the total number of images."""
        return len(self.input_paths)


from socket import *
import sys
from threading import *
from datetime import datetime
import os
import art

def clear():

    if os.name == 'nt':
        _ = os.system('cls')
    else:
        _ = os.system('clear')
clear()

print(art.text2art("                                         Port  Scanner"))

try:
    host = input("\nEnter the Domain name/ ip address =  ")
    resolvedip = gethostbyname(host)
except:
    sys.exit("Check your domain , Entered domain not found")

normalPortStart = 1
normalPortEnd = 1024
allPort = 1
allPortEnd = 65535
customPortStart = 0
customPortEnd = 0

print('\n')
now = datetime.now()
current_time = now.strftime("%H:%M:%S")
print("Select your scan type: ")
print("[+] Select 1 for Normal Ports scaning")
print("[+] Select 2 for All Ports scaning")
print("[+] Select 3 for custom port scaning")
print("[+] Select 4 for exit \n")

mode = int(input("[+] Select any option: "))
print()

if mode == 3:
    customPortStart = int(input("[+] Enter starting port number: "))
    customPortEnd = int(input("[+] Enter ending port number: "))

print("-"*50)
print(f"Target IP: {host}")
print("Scanning started at:" + str(datetime.now()))
print("-"*50)

allports = []
def get_ports(mode):
    if mode == 1:
        print("\n[+] scaning..\n")
        for port in range(normalPortStart, normalPortEnd+1):
            allports.append(port)
    elif mode == 2:
        print("\n[+] scaning..\n")
        for port in range(allPort, allPortEnd+1):
            allports.append(port)
    elif mode == 3:
        print("\n[+] scaning..\n")
        for port in range(customPortStart, customPortEnd+1):
            allports.append(port)
    elif mode == 4:
        print("[-] Exiting...")
        sys.exit()

setdefaulttimeout(0.01)
lock = Lock()
thread_array = []
main_array = []

def conn(ipx,portx,lock,mode):
    addr = (ipx,portx)
    s = socket(AF_INET,SOCK_STREAM)
    result = s.connect_ex(addr)
    s.close()
    lock.acquire()
    if(result == 0):
        main_array.append(portx)
        print("Port ",format(portx)," is open")
    else:
        print("Port ",format(portx)," is not open")
    lock.release()

get_ports(mode)
for port in allports:
    t = Thread(target = conn , args = (host,port,lock,mode))
    thread_array.append(t)
    t.start()

for thread in thread_array:
    thread.join()

print("-"*50)
print("port that are open are ",main_array)
print("-"*50)

print(f"Scanning compleate in: {current_time}")