# pip install mediapipe (it will install openCV and numPy together)

import cv2
import math
import time
import mediapipe as mp
import subprocess
import json

mp_hands = mp.solutions.hands

# .-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------.
# | Palm Status |    Handedness    | Angle Requirement |                Finger Requirement                 |     State Requirement      |      Outcome     |        State Change        |
# |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
# |  Palm Far   |        -         |         -         |                      All Open                     |           CLOSED           |      Open TV     |            OPEN            |
# |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
# |  Palm Near  |        -         |         -         |                     All Closed                    |            OPEN            |     Close TV     |           CLOSED           |
# |  Palm Far   |  Only Left Hand  |      Angle 0      |             Thumb Open, Others Closed             |            OPEN            |     Volume Up    |             -              |
# |  Palm Near  |  Only Left Hand  |      Angle 0      |             Thumb Open, Others Closed             |            OPEN            |    Volume Down   |             -              |
# |  Palm Far   | Only Right Hand  |     Angle 180     |             Thumb Closed, Others Open             |            OPEN            | Previous Channel |             -              |
# |  Palm Far   |  Only Left Hand  |      Angle 0      |             Thumb Closed, Others Open             |            OPEN            |   Next Channel   |             -              |
# |  Palm Near  |        -         |      Angle 90     |                      All Open                     |            OPEN            |    Toggle Mute   |             -              |
# |  Palm Near  |  Only Left Hand  |      Angle 90     |       Thumb-Index Finger Open, Others Closed      |            OPEN            |   Begin Channel  |   ENTERING_CHANNEL_FIRST   |
# |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
# |  Palm Near  |  Only Left Hand  |         -         |                     All Closed                    |      ENTERING_CHANNEL      |   Channel -> 0   |            OPEN            |
# |  Palm Near  |  Only Left Hand  |         -         |             Thumb Open, Others Closed             |      ENTERING_CHANNEL      |   Channel -> 1   |            OPEN            |
# |  Palm Near  |  Only Left Hand  |         -         |     Thumb to Index Finger Open, Others Closed     |      ENTERING_CHANNEL      |   Channel -> 2   |            OPEN            |
# |  Palm Near  |  Only Left Hand  |         -         |     Thumb to Middle Finger Open, Others Closed    |      ENTERING_CHANNEL      |   Channel -> 3   |            OPEN            |
# |  Palm Near  |  Only Left Hand  |         -         |      Thumb to Ring Finger Open, Others Closed     |      ENTERING_CHANNEL      |   Channel -> 4   |            OPEN            |
# |  Palm Near  |  Only Left Hand  |         -         |                      All Open                     |      ENTERING_CHANNEL      |   Channel -> 5   |            OPEN            |
# |  Palm Near  |  Only Left Hand  |         -         |             Pinky Open, Others Closed             |      ENTERING_CHANNEL      |   Channel -> 6   |            OPEN            |
# |  Palm Near  |  Only Left Hand  |         -         |      Pinky to Ring Finger Open, Others Closed     |      ENTERING_CHANNEL      |   Channel -> 7   |            OPEN            |
# |  Palm Near  |  Only Left Hand  |         -         |     Pinky to Middle Finger Open, Others Closed    |      ENTERING_CHANNEL      |   Channel -> 8   |            OPEN            |
# |  Palm Near  |  Only Left Hand  |         -         |     Pinky to Index Finger Open, Others Closed     |      ENTERING_CHANNEL      |   Channel -> 9   |            OPEN            |
# |  Palm Far   |  Only Right Hand |         -         |                      All Open                     |      ENTERING_CHANNEL      |   Stop Editing   |            OPEN            |
# '-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------'

class RemoteController():
    # States
    CLOSED = 0
    OPEN = 1
    ENTERING_CHANNEL = 2

    # Possible readings
    CLOSE_TV = 10
    OPEN_TV = 11
    VOLUME_UP = 12
    VOLUME_DOWN = 13
    PREV_CHANNEL = 14
    NEXT_CHANNEL = 15
    TOGGLE_MUTE = 16
    GO_CHANNEL = 17
    STOP_EDITTING = 18

    # Numbers
    NUMBER_ZERO = 20
    NUMBER_ONE = 21
    NUMBER_TWO = 22
    NUMBER_THREE = 23
    NUMBER_FOUR = 24
    NUMBER_FIVE = 25
    NUMBER_SIX = 26
    NUMBER_SEVEN = 27
    NUMBER_EIGHT = 28
    NUMBER_NINE = 29

    # ir-ctl related options
    EXE_PATH = "/usr/bin/ir-ctl"
    PROTOCOL = "nec"
    DEVICE = "/dev/lirc0"

    def __init__(self, enable_debug=False, acceptance_count=50, rejection_count=10, sleep_between_decimals=0.75):
        self.hand_interpreter = mp_hands.Hands(min_detection_confidence=0.6, min_tracking_confidence=0.6, max_num_hands=1)
        self.capture = cv2.VideoCapture(0)

        self.enable_debug = enable_debug
        self.acceptance_count = acceptance_count
        self.rejection_count = rejection_count
        self.sleep_between_decimals = sleep_between_decimals

        self.last_read_input = -1
        self.last_read_input_count = 0
        self.last_read_threshold_count = 0

        self.state = RemoteController.CLOSED
        self.is_muted = False
        self.channel_number = []

        fp = open('key_codes.json', 'r')
        self.key_codes = json.load(fp)
        fp.close()

    # It basically returns wrist coordinates and MCP (bottom of any finger) averaged (between middle and ring fingers) coordinates
    def important_coord_calculation(self):
        wrist_coords = (self.landmarks[mp_hands.HandLandmark.WRIST].x * self.width, self.landmarks[mp_hands.HandLandmark.WRIST].y * self.height)
        mcp_average_coords = ((self.landmarks[mp_hands.HandLandmark.MIDDLE_FINGER_MCP].x + self.landmarks[mp_hands.HandLandmark.RING_FINGER_MCP].x) * self.width / 2.0, (self.landmarks[mp_hands.HandLandmark.MIDDLE_FINGER_MCP].y + self.landmarks[mp_hands.HandLandmark.RING_FINGER_MCP].y) * self.height / 2.0)

        return (wrist_coords, mcp_average_coords)

    # First value in radians, second in degrees
    def angle_calculation(self, wrist_coords, mcp_average_coords):
        angle_rad = math.atan2(wrist_coords[1] - mcp_average_coords[1], mcp_average_coords[0] - wrist_coords[0])
        angle_deg = (angle_rad / (2 * math.pi) * 360.0 + 360.0) % 360.0

        if self.enable_debug:
            cv2.putText(self.image, "Angle: %.2f" % angle_deg, (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

        return (angle_rad, angle_deg)

    # Order: thumb, index finger, middle finger, ring finger, pinky, circle center (x, y), radius
    def finger_inside_palm(self, wrist_coords, mcp_average_coords):
        center = ((wrist_coords[0] + mcp_average_coords[0]) / 2.0, (wrist_coords[1] + mcp_average_coords[1]) / 2.0)
        radius = math.sqrt((wrist_coords[0] - mcp_average_coords[0]) ** 2 + (wrist_coords[1] - mcp_average_coords[1]) ** 2)
        squared_radius = radius ** 2

        thumb_tip = (self.landmarks[mp_hands.HandLandmark.THUMB_TIP].x * self.width, self.landmarks[mp_hands.HandLandmark.THUMB_TIP].y * self.height)
        index_finger_tip = (self.landmarks[mp_hands.HandLandmark.INDEX_FINGER_TIP].x * self.width, self.landmarks[mp_hands.HandLandmark.INDEX_FINGER_TIP].y * self.height)
        middle_finger_tip = (self.landmarks[mp_hands.HandLandmark.MIDDLE_FINGER_TIP].x * self.width, self.landmarks[mp_hands.HandLandmark.MIDDLE_FINGER_TIP].y * self.height)
        ring_finger_tip = (self.landmarks[mp_hands.HandLandmark.RING_FINGER_TIP].x * self.width, self.landmarks[mp_hands.HandLandmark.RING_FINGER_TIP].y * self.height)
        pinky_tip = (self.landmarks[mp_hands.HandLandmark.PINKY_TIP].x * self.width, self.landmarks[mp_hands.HandLandmark.PINKY_TIP].y * self.height)

        is_thumb_inside = ((thumb_tip[0] - center[0]) ** 2 + (thumb_tip[1] - center[1]) ** 2) < squared_radius
        is_index_finger_inside = ((index_finger_tip[0] - center[0]) ** 2 + (index_finger_tip[1] - center[1]) ** 2) < squared_radius
        is_middle_finger_inside = ((middle_finger_tip[0] - center[0]) ** 2 + (middle_finger_tip[1] - center[1]) ** 2) < squared_radius
        is_ring_finger_inside = ((ring_finger_tip[0] - center[0]) ** 2 + (ring_finger_tip[1] - center[1]) ** 2) < squared_radius
        is_pinky_inside = ((pinky_tip[0] - center[0]) ** 2 + (pinky_tip[1] - center[1]) ** 2) < squared_radius

        if self.enable_debug:
            cv2.putText(self.image, "Values: {}, {}, {}, {}, {}".format(is_thumb_inside, is_index_finger_inside, is_middle_finger_inside, is_ring_finger_inside, is_pinky_inside), (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

            self.image = cv2.circle(self.image, (int(center[0]), int(center[1])), int(radius), (0, 255, 0), 2)

        return (is_thumb_inside, is_index_finger_inside, is_middle_finger_inside, is_ring_finger_inside, is_pinky_inside, center, radius)

    def hand_orientation(self):
        avg_coord = ((self.landmarks[mp_hands.HandLandmark.MIDDLE_FINGER_MCP].x + self.landmarks[mp_hands.HandLandmark.RING_FINGER_MCP].x) / 2.0, 1.0 - (self.landmarks[mp_hands.HandLandmark.MIDDLE_FINGER_MCP].y + self.landmarks[mp_hands.HandLandmark.RING_FINGER_MCP].y) / 2.0, (self.landmarks[mp_hands.HandLandmark.MIDDLE_FINGER_MCP].z + self.landmarks[mp_hands.HandLandmark.RING_FINGER_MCP].z) / 2.0)
        wrist_coord = (self.landmarks[mp_hands.HandLandmark.WRIST].x, 1.0 - self.landmarks[mp_hands.HandLandmark.WRIST].y, self.landmarks[mp_hands.HandLandmark.WRIST].z)
        thumb_cmc_coord = (self.landmarks[mp_hands.HandLandmark.THUMB_CMC].x, 1.0 - self.landmarks[mp_hands.HandLandmark.THUMB_CMC].y, self.landmarks[mp_hands.HandLandmark.THUMB_CMC].z)

        vector_1 = (avg_coord[0] - wrist_coord[0], avg_coord[1] - wrist_coord[1], avg_coord[2] - wrist_coord[2])
        vector_2 = (thumb_cmc_coord[0] - wrist_coord[0], thumb_cmc_coord[1] - wrist_coord[1], thumb_cmc_coord[2] - wrist_coord[2])

        orientation = (vector_1[1] * vector_2[2] - vector_1[2] * vector_2[1], vector_1[2] * vector_2[0] - vector_1[0] * vector_2[2], vector_1[0] * vector_2[1] - vector_1[1] * vector_2[0])

        is_palm_near = False if (orientation[2] > 0 and self.hand_label == "Left") or (orientation[2] < 0 and self.hand_label == "Right") else True

        if self.enable_debug:
            cv2.putText(self.image, "Orientation: {}".format("Palm Near" if is_palm_near else "Palm Far"), (10, 120), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

        return (orientation, is_palm_near)

    def state_process(self, conditions_inputs_and_outcomes):
        has_match = False

        for element in conditions_inputs_and_outcomes:
            if element[0]:
                self.last_read_threshold_count = 0

                if self.last_read_input != element[1]:
                    self.last_read_input = element[1]
                    self.last_read_input_count = 0
                else:
                    self.last_read_input_count += 1

                if self.last_read_input_count >= self.acceptance_count:
                    self.state = element[2]

                    self.last_read_input = -1
                    self.last_read_input_count = 0
                    self.last_read_threshold_count = 0

                    if len(element) == 4:
                        element[3]()
                    elif len(element) == 5:
                        element[3](element[4])

                has_match = True

                break

        if not has_match and self.last_read_input != -1:
            self.last_read_threshold_count += 1

            if self.last_read_threshold_count >= self.rejection_count:
                self.last_read_input = -1
                self.last_read_input_count = 0
                self.last_read_threshold_count = 0

        if self.enable_debug:
            cv2.putText(self.image, "State: {}".format(self.state), (10, 150), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
            cv2.putText(self.image, "Input: {}".format(self.last_read_input), (10, 180), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
            cv2.putText(self.image, "Input Count: {}".format(self.last_read_input_count), (10, 210), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
            cv2.putText(self.image, "Threshold Count: {}".format(self.last_read_threshold_count), (10, 240), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

    def reset(self):
        self.last_read_input = -1
        self.last_read_input_count = 0
        self.last_read_threshold_count = 0

        self.state = RemoteController.CLOSED
        self.is_muted = False
        self.channel_number = []

    def ir_command_helper(self, hex_code):
        command = [self.EXE_PATH, "-S", "{}:{}".format(self.PROTOCOL, hex_code), "-d", self.DEVICE]
        result = subprocess.call(command)

        return result

    def string_channel_number(self):
        return "".join(map(lambda x: str(x), self.channel_number)).lstrip("0")

    def open_tv_function(self):
        self.ir_command_helper(self.key_codes["KEY_POWER"])
        print('TV opened')

    def close_tv_function(self):
        self.ir_command_helper(self.key_codes["KEY_POWER"])
        print('TV closed')

    def volume_up_function(self):
        self.ir_command_helper(self.key_codes["KEY_VOLUME_UP"])
        print('Volume increased')

    def volume_down_function(self):
        self.ir_command_helper(self.key_codes["KEY_VOLUME_DOWN"])
        print('Volume decreased')

    def prev_channel_function(self):
        self.ir_command_helper(self.key_codes["KEY_PREV_CHANNEL"])
        print('Go previous channel')

    def next_channel_function(self):
        self.ir_command_helper(self.key_codes["KEY_NEXT_CHANNEL"])
        print('Go next channel')

    def toggle_mute(self):
        self.ir_command_helper(self.key_codes["KEY_MUTE"])
        self.is_muted = not self.is_muted

        if self.is_muted:
            print('Now muted')
        else:
            print('Mute deactivated')

    def go_channel(self):
        print('Started channel selection process')

    def add_decimal(self, decimal):
        self.channel_number.append(decimal)

        print("Current number: {}".format(self.string_channel_number()))

    def stop_editting(self):
        new_list = []
        is_elapsed = False

        for decimal in self.channel_number:
            if decimal != 0:
                is_elapsed = True

            if is_elapsed:
                new_list.append(decimal)

        if len(new_list) == 0:
            print("No channel number is entered!")
        else:
            for decimal in new_list:
                if decimal == 0:
                    self.ir_command_helper(self.key_codes["KEY_ZERO"])
                elif decimal == 1:
                    self.ir_command_helper(self.key_codes["KEY_ONE"])
                elif decimal == 2:
                    self.ir_command_helper(self.key_codes["KEY_TWO"])
                elif decimal == 3:
                    self.ir_command_helper(self.key_codes["KEY_THREE"])
                elif decimal == 4:
                    self.ir_command_helper(self.key_codes["KEY_FOUR"])
                elif decimal == 5:
                    self.ir_command_helper(self.key_codes["KEY_FIVE"])
                elif decimal == 6:
                    self.ir_command_helper(self.key_codes["KEY_SIX"])
                elif decimal == 7:
                    self.ir_command_helper(self.key_codes["KEY_SEVEN"])
                elif decimal == 8:
                    self.ir_command_helper(self.key_codes["KEY_EIGHT"])
                elif decimal == 9:
                    self.ir_command_helper(self.key_codes["KEY_NINE"])

                time.sleep(self.sleep_between_decimals)

            print("Go to channel number {}".format(self.string_channel_number()))

            self.channel_number = []

    def main_execution(self):
        while self.capture.isOpened():
            success, image = self.capture.read()

            start_time = time.time()

            if not success:
                print("Ignoring empty camera frame.")
                continue

            image = cv2.cvtColor(cv2.flip(image, 1), cv2.COLOR_BGR2RGB)

            self.height, self.width = image.shape[:2]

            image.flags.writeable = False
            results = self.hand_interpreter.process(image)

            image.flags.writeable = True
            self.image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)

            if results.multi_hand_landmarks:
                hand_landmark = results.multi_hand_landmarks[0]
                self.landmarks = hand_landmark.landmark

                handedness = results.multi_handedness[0]
                handedness_classification = handedness.classification[0]
                self.hand_label = handedness_classification.label

                (wrist_coords, mcp_average_coords) = self.important_coord_calculation()

                (angle_rad, angle_deg) = self.angle_calculation(wrist_coords, mcp_average_coords)

                (is_thumb_inside, is_index_finger_inside, is_middle_finger_inside, is_ring_finger_inside, is_pinky_inside, center, radius) = self.finger_inside_palm(wrist_coords, mcp_average_coords)

                (orientation, is_palm_near) = self.hand_orientation()

                if self.state == RemoteController.CLOSED:
                    open_tv_payload = (
                        not is_palm_near and not is_thumb_inside and not is_index_finger_inside and not is_middle_finger_inside and not is_ring_finger_inside and not is_pinky_inside,
                        RemoteController.OPEN_TV,
                        RemoteController.OPEN,
                        self.open_tv_function,
                    )

                    self.state_process((open_tv_payload, ))
                elif self.state == RemoteController.OPEN:
                    close_tv_payload = (
                        is_palm_near and is_thumb_inside and is_index_finger_inside and is_middle_finger_inside and is_ring_finger_inside and is_pinky_inside,
                        RemoteController.CLOSE_TV,
                        RemoteController.CLOSED,
                        self.close_tv_function,
                    )
                    volume_up_payload = (
                        self.hand_label == "Left" and (angle_deg < 30.0 or angle_deg > 330.0) and not is_palm_near and not is_thumb_inside and is_index_finger_inside and is_middle_finger_inside and is_ring_finger_inside and is_pinky_inside,
                        RemoteController.VOLUME_UP,
                        RemoteController.OPEN,
                        self.volume_up_function,
                    )
                    volume_down_payload = (
                        self.hand_label == "Left" and (angle_deg < 30.0 or angle_deg > 330.0) and is_palm_near and not is_thumb_inside and is_index_finger_inside and is_middle_finger_inside and is_ring_finger_inside and is_pinky_inside,
                        RemoteController.VOLUME_DOWN,
                        RemoteController.OPEN,
                        self.volume_down_function,
                    )
                    prev_channel_payload = (
                        self.hand_label == "Right" and (angle_deg < 210.0 or angle_deg > 150.0) and not is_palm_near and is_thumb_inside and not is_index_finger_inside and not is_middle_finger_inside and not is_ring_finger_inside and not is_pinky_inside,
                        RemoteController.PREV_CHANNEL,
                        RemoteController.OPEN,
                        self.prev_channel_function,
                    )
                    next_channel_payload = (
                        self.hand_label == "Left" and (angle_deg < 30.0 or angle_deg > 330.0) and not is_palm_near and is_thumb_inside and not is_index_finger_inside and not is_middle_finger_inside and not is_ring_finger_inside and not is_pinky_inside,
                        RemoteController.NEXT_CHANNEL,
                        RemoteController.OPEN,
                        self.next_channel_function,
                    )
                    toggle_mute_payload = (
                        (angle_deg < 120.0 or angle_deg > 60.0) and is_palm_near and not is_thumb_inside and not is_index_finger_inside and not is_middle_finger_inside and not is_ring_finger_inside and not is_pinky_inside,
                        RemoteController.TOGGLE_MUTE,
                        RemoteController.OPEN,
                        self.toggle_mute,
                    )
                    begin_channel_payload = (
                        self.hand_label == "Left" and (angle_deg < 120.0 or angle_deg > 60.0) and is_palm_near and is_thumb_inside and is_index_finger_inside and not is_middle_finger_inside and not is_ring_finger_inside and not is_pinky_inside,
                        RemoteController.GO_CHANNEL,
                        RemoteController.ENTERING_CHANNEL,
                        self.go_channel,
                    )

                    self.state_process((close_tv_payload, volume_up_payload, volume_down_payload, prev_channel_payload, next_channel_payload, toggle_mute_payload, begin_channel_payload))
                elif self.state == RemoteController.ENTERING_CHANNEL:
                    number_zero_payload = (
                        self.hand_label == "Left" and is_palm_near and is_thumb_inside and is_index_finger_inside and is_middle_finger_inside and is_ring_finger_inside and is_pinky_inside,
                        RemoteController.NUMBER_ZERO,
                        RemoteController.ENTERING_CHANNEL,
                        self.add_decimal,
                        0,
                    )
                    number_one_payload = (
                        self.hand_label == "Left" and is_palm_near and not is_thumb_inside and is_index_finger_inside and is_middle_finger_inside and is_ring_finger_inside and is_pinky_inside,
                        RemoteController.NUMBER_ONE,
                        RemoteController.ENTERING_CHANNEL,
                        self.add_decimal,
                        1,
                    )
                    number_two_payload = (
                        self.hand_label == "Left" and is_palm_near and not is_thumb_inside and not is_index_finger_inside and is_middle_finger_inside and is_ring_finger_inside and is_pinky_inside,
                        RemoteController.NUMBER_TWO,
                        RemoteController.ENTERING_CHANNEL,
                        self.add_decimal,
                        2,
                    )
                    number_three_payload = (
                        self.hand_label == "Left" and is_palm_near and not is_thumb_inside and not is_index_finger_inside and not is_middle_finger_inside and is_ring_finger_inside and is_pinky_inside,
                        RemoteController.NUMBER_THREE,
                        RemoteController.ENTERING_CHANNEL,
                        self.add_decimal,
                        3,
                    )
                    number_four_payload = (
                        self.hand_label == "Left" and is_palm_near and not is_thumb_inside and not is_index_finger_inside and not is_middle_finger_inside and not is_ring_finger_inside and is_pinky_inside,
                        RemoteController.NUMBER_FOUR,
                        RemoteController.ENTERING_CHANNEL,
                        self.add_decimal,
                        4,
                    )
                    number_five_payload = (
                        self.hand_label == "Left" and is_palm_near and not is_thumb_inside and not is_index_finger_inside and not is_middle_finger_inside and not is_ring_finger_inside and not is_pinky_inside,
                        RemoteController.NUMBER_FIVE,
                        RemoteController.ENTERING_CHANNEL,
                        self.add_decimal,
                        5,
                    )
                    number_six_payload = (
                        self.hand_label == "Left" and is_palm_near and is_thumb_inside and is_index_finger_inside and is_middle_finger_inside and is_ring_finger_inside and not is_pinky_inside,
                        RemoteController.NUMBER_SIX,
                        RemoteController.ENTERING_CHANNEL,
                        self.add_decimal,
                        6,
                    )
                    number_seven_payload = (
                        self.hand_label == "Left" and is_palm_near and is_thumb_inside and is_index_finger_inside and is_middle_finger_inside and not is_ring_finger_inside and not is_pinky_inside,
                        RemoteController.NUMBER_SEVEN,
                        RemoteController.ENTERING_CHANNEL,
                        self.add_decimal,
                        7,
                    )
                    number_eight_payload = (
                        self.hand_label == "Left" and is_palm_near and is_thumb_inside and is_index_finger_inside and not is_middle_finger_inside and not is_ring_finger_inside and not is_pinky_inside,
                        RemoteController.NUMBER_EIGHT,
                        RemoteController.ENTERING_CHANNEL,
                        self.add_decimal,
                        8,
                    )
                    number_nine_payload = (
                        self.hand_label == "Left" and is_palm_near and is_thumb_inside and not is_index_finger_inside and not is_middle_finger_inside and not is_ring_finger_inside and not is_pinky_inside,
                        RemoteController.NUMBER_NINE,
                        RemoteController.ENTERING_CHANNEL,
                        self.add_decimal,
                        9,
                    )
                    stop_editting = (
                        self.hand_label == "Right" and not is_palm_near and not is_thumb_inside and not is_index_finger_inside and not is_middle_finger_inside and not is_ring_finger_inside and not is_pinky_inside,
                        RemoteController.STOP_EDITTING,
                        RemoteController.OPEN,
                        self.stop_editting,
                    )

                    self.state_process((number_zero_payload, number_one_payload, number_two_payload, number_three_payload, number_four_payload, number_five_payload, number_six_payload, number_seven_payload, number_eight_payload, number_nine_payload, stop_editting))

            stop_time = time.time()
            fps = 1.0 / (stop_time - start_time)

            if self.enable_debug:
                cv2.putText(self.image, "FPS: %.2f" % fps, (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)

            cv2.imshow('Remote Control', self.image)

            key = cv2.waitKey(5) & 0xFF

            if key == 27:
                break
            elif key == 114 and self.enable_debug:
                self.reset()

        self.hand_interpreter.close()
        self.capture.release()

if __name__ == "__main__":
    controller = RemoteController(enable_debug=True, acceptance_count=25, rejection_count=10, sleep_between_decimals=0.75)
    controller.main_execution()


import torch
import numpy as np
from scipy import special
from ising_model import IsingModel
from main import decimal_to_binary_tensor

class ModelPartition:
    def __init__(self, model):
        self.model = model
        self.num_spins = self.model.num_spins
        self.num_cols = self.model.num_cols
        self.num_rows = self.model.num_rows
        self.num_edges = self.model.num_edges
        self.J = self.model.J
        self.phi, self.Jdiag, self.A = self.prep_Z_anal()

    def get_Z_true(self, beta):
        """calculate the partition function of Ising model for a given beta """
        num_state = 2 ** self.num_spins
        Z = 0.
        for i_state in range(num_state):
            binary = decimal_to_binary_tensor(i_state, width=self.num_spins)
            spin_state = 1 - 2 * binary
            H = self.model.get_hamiltonian(spin_state)
            Z += torch.exp(- beta * H)
        return Z

    def get_energy_true(self, beta):
        """calculate the expectation value of the Energy of Ising model with Boltzmann distribution """
        num_state = 2 ** self.num_spins
        Z = self.get_Z_true(beta)
        energy = 0.
        for i_state in range(num_state):
            binary = decimal_to_binary_tensor(i_state, width=self.num_spins)
            spin_state = 1 - 2 * binary
            H = self.model.get_hamiltonian(spin_state)
            energy += H * torch.exp(- beta * H)
        return energy / Z

    def get_m_square_true(self, beta):
        """calculate the expectation value of square of the magnetisation in Ising model with Boltzmann distribution """
        num_state = 2 ** self.num_spins
        Z = self.get_Z_true(beta)
        m_square = 0.
        for i_state in range(num_state):
            binary = decimal_to_binary_tensor(i_state, width=self.num_spins)
            spin_state = 1 - 2 * binary
            m = self.get_magnetisation(spin_state)
            H = self.get_hamiltonian(spin_state)
            m_square += m * m * torch.exp(- beta * H)
        return m_square / Z

    def get_entropy_true(self, beta):
        """calculate the entropy of Ising model with Boltzmann distribution """
        Z = self.get_Z_true(beta).unsqueeze(0)
        return beta * self.get_energy_true(beta) + torch.log(Z)

    def get_energy_onsager(self, beta, interaction):
        """Onsager solution; analytic solution of energy for the infinite 2d square Ising lattice """
        if interaction == 'ferromagnetic':
            J = 1.
        elif interaction == 'anti-ferromagnetic':
            J = -1.
        else:
            raise Exception("invalid interaction type for this function")
        b = 2 * beta * J
        a = 2 * np.tanh(b) / np.cosh(b)
        K = special.ellipk(a ** 2)
        U = - J / np.tanh(b) * (1 + 2 / np.pi * (2 * np.tanh(b) ** 2 - 1) * K) / 2
        return U

    def prep_Z_anal(self):
        """preparation procedure for calculation of Z_analytic """
        L = self.num_cols
        nedge = self.num_edges
        J = self.J

        # angle between two (different) connected edges; set default angle = 1 which means two edges are disconnected
        phi = torch.ones(2 * nedge, 2 * nedge)

        # tensor A which is required when calculating W=AD in Z_analytic
        A = torch.zeros((2 * nedge, 2 * nedge), dtype=torch.cfloat)

        # reform (nspin, nspin) matrix J[i,j] to a diagonal (2*nedge, 2*nedge) matrix J[ij,ij]; required to get a tensor D in W=AD
        Jdiag = torch.zeros((2 * nedge, 2 * nedge), dtype=torch.cfloat)
        for e1 in range(2 * nedge):
            if e1 < nedge:
                i, j = self.model.get_vertices(e1)            # e1 = (i,j) is a directed edge from i to j
                Jdiag[e1, e1] = J[i, j]
            else:
                j, i = self.model.get_vertices(e1 - nedge)    # the inversed e1 above; i here is j above and j here is i above
                Jdiag[e1, e1] = J[i, j]
            for e2 in range(2 * nedge):
                if e2 < nedge:
                    k, l = self.model.get_vertices(e2)            # e2 = (k,l) is a directed edge from i to j
                else:
                    l, k = self.model.get_vertices(e2 - nedge)    # the inversed e2 above; k here is l above and l here is k above
                # phi[e1,e2] means the angle between two edges e1=(i,j) and e2=(k,l) when j==k and i!=l
                if j == k and i != l:
                    if (i==j-1 and l==j-L) or (i==j-L and l==j+1) or (i==j+1 and l==j+L) or (i==j+L and l==j-1):
                        phi[e1, e2] = np.pi / 2
                    elif (l==j-1 and i==j-L) or (l==j-L and i==j+1) or (l==j+1 and i==j+L) or (l==j+L and i==j-1):
                        phi[e1, e2] = -np.pi / 2
                    elif i-l== -2 or i-l==2 or i-l== -2*L or i-l==2*L:
                        phi[e1, e2] = 0
                    # get an element A[e1, e2] in terms of phi[e1, e2]
                    A[e1, e2] = np.exp(0.5 * 1j * phi[e1, e2])
        return phi, Jdiag, A

    def get_Z_anal(self, beta):
        """analytic solution of partition function for 2d square Ising lattice even with the random bond J = 1 or -1 """
        nspin = self.num_spins
        nedge = self.num_edges
        A = self.A
        theta = - beta * self.J
        D = torch.tanh(- beta * self.Jdiag)
        W = torch.matmul(A,D)
        I = torch.eye(2 * nedge)
        PIproduct = 1
        for i in range(nspin):
            for j in range(i, nspin):
                if theta[i,j] != 0:
                    PIproduct *= np.cosh(theta[i,j])
        Z = pow(2,nspin) * PIproduct * np.sqrt(torch.det(I-W))
        return Z.real

    def get_energy_anal(self, beta):
        """calculate energy from taking beta-derivative of Z_analytic """
        nspin = self.num_spins
        nedge = self.num_edges
        A = self.A
        theta = - beta * self.J
        D = torch.tanh(- beta * self.Jdiag)
        W = torch.matmul(A, D)
        Jdiag = self.Jdiag
        I = torch.eye(2 * nedge)
        term1 = 0
        for i in range(nspin):
            for j in range(i, nspin):
                if theta[i, j] != 0:
                    term1 += np.tanh(theta[i, j]) * self.J[i, j]
        tr_input1 = torch.matmul(torch.inverse(I-W), A)
        tr_input2 = torch.matmul(I-torch.tanh(-beta * Jdiag)**2, Jdiag)
        term2 = -0.5 * torch.trace(torch.matmul(tr_input1, tr_input2))
        E = term1 + term2
        return E.real


from collections import defaultdict

from selenium_profiles import webdriver
from selenium_profiles.profiles import profiles

PROFILE = {"Windows": {
    "options": {
      "gpu": 'ANGLE (Intel, Intel(R) HD Graphics 520 Direct3D11 vs_5_0 ps_5_0, D3D11-30.0.101.1338)',
      "window_size": {
          "x": 1366,
          "y": 768}
    },
    "cdp": {
      "touch": True,
      "maxtouchpoints": 10,
      "cores": 4,
      "patch_version": True,
      "emulation": {"mobile":False,"width": 1366, "height": 768, "deviceScaleFactor": 1,
        "screenOrientation": {"type": "landscapePrimary", "angle": 0}},
      "useragent": {
                "platform": "Win32",
                "acceptLanguage":"en-US",
                "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
                "userAgentMetadata": {
                    "brands": [{"brand":"Google Chrome","version":"114"},
                              {"brand":"Chromium","version":"114"},
                              {"brand":"Not=A?Brand","version":"24"}],
                    "fullVersionList": [{"brand":"Google Chrome","version":"114.0.5735.134"},
                                        {"brand":"Chromium","version":"114.0.5735.134"},
                                        {"brand":"Not=A?Brand","version":"24.0.0.0"}],
                    "fullVersion": "114.0.5735.134",
                    "platform": "Windows",
                    "platformVersion": "10.0.19045",
                    "architecture": "x86",
                    "model": "",
                    "mobile": False,
                    "bitness": "64",
                    "wow64": False}
      }
    }
  }
}

def return_profile(json_prof):
    from selenium_profiles.utils.utils import read_json
    profile = defaultdict(lambda: None)
    profile.update(read_json(json_prof))
    return profile  # yet supported: "Android", "Windows"

prof_to_driver = return_profile(PROFILE)
mydriver = webdriver.Chrome(prof_to_driver, uc_driver=False) # or pass seleniumwire-options
driver = mydriver.start()

# get url
try:
    driver.get('https://abrahamjuliot.github.io/creepjs/')  # test fingerprint

    # input("Press ENTER to exit: ")
finally:
    driver.quit()  # Execute on the End!


import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
np.random.seed(999)
torch.backends.cudnn.deterministic = True
torch.manual_seed(999)
torch.backends.cudnn.deterministic = True
torch.cuda.manual_seed_all(999)

class Unit(nn.Module):
    def __init__(self, in_channels, out_channels):
        super(Unit, self).__init__()
        self.conv = nn.Conv2d(in_channels=in_channels, kernel_size=3, out_channels=out_channels, stride=1, padding=1)
        self.bn = nn.BatchNorm2d(num_features=out_channels)
        self.relu = nn.ReLU()

    def forward(self, input):
        output = self.conv(input)
        output = self.bn(output)
        output = self.relu(output)
        return output

class DeepMoonClassifier(nn.Module):
    def __init__(self, num_classes=10):
        super(DeepMoonClassifier, self).__init__()

        #Create 14 layers of the unit with max pooling in between
        self.unit1 = Unit(in_channels=1, out_channels=32)
        self.unit2 = Unit(in_channels=32, out_channels=32)
        self.unit3 = Unit(in_channels=32, out_channels=32)

        self.pool1 = nn.MaxPool2d(kernel_size=2)

        self.unit4 = Unit(in_channels=32, out_channels=64)
        self.unit5 = Unit(in_channels=64, out_channels=64)
        self.unit6 = Unit(in_channels=64, out_channels=64)
        self.unit7 = Unit(in_channels=64, out_channels=64)

        self.pool2 = nn.MaxPool2d(kernel_size=2)

        self.unit8 = Unit(in_channels=64, out_channels=64)
        self.unit9 = Unit(in_channels=64, out_channels=64)
        self.unit10 = Unit(in_channels=64, out_channels=64)
        self.unit11 = Unit(in_channels=64, out_channels=64)

        self.pool3 = nn.MaxPool2d(kernel_size=2)

        self.unit12 = Unit(in_channels=64, out_channels=128)
        self.unit13 = Unit(in_channels=128, out_channels=128)
        self.unit14 = Unit(in_channels=128, out_channels=128)
        self.unit15 = Unit(in_channels=128, out_channels=128)
        self.unit16 = Unit(in_channels=128, out_channels=128)

        self.avgpool = nn.AvgPool2d(kernel_size=4)

        #Add all the units into the Sequential layer in exact order
        self.net = nn.Sequential(self.unit1, self.unit2, self.unit3, self.pool1, self.unit4,self.unit5,  self.unit6,
                                 self.unit7, self.pool2, self.unit8, self.unit9, self.unit10, self.unit11,self.pool3,
                                 self.unit12, self.avgpool)

        self.fc = nn.Linear(in_features=128, out_features=num_classes)

    def forward(self, input):
        output = self.net(input)
        output = output.view(-1, 128)
        output = self.fc(output)
        return output


#!/usr/bin/env python3
import os
import argparse
import numpy as np
import csv

import rospy
import rospkg
from geometry_msgs.msg import Pose2D
from pedsim_msgs.msg  import GymAgentInfo
from pedsim_srvs.srv import GymReset, GymResetRequest, GymResetResponse
from gazebo_msgs.srv import GetWorldProperties

MOVING_DISTANCE = 4.0

if __name__ == '__main__':
    rospy.init_node("gym_reset_node")

    # Convert arguments
    parser = argparse.ArgumentParser(description='Reset the humans of Pedsim like OpenAI Gym environment.')
    parser.add_argument('--use_testcase', default=False, action='store_true')
    parser.add_argument('--num_agents', type=int, default='8')
    parser.add_argument('--testcase', type=int, default=1)
    tmp_args = rospy.myargv()   # args which included 'ros related' arguments, need to be filtered
    args = parser.parse_args(tmp_args[1:])

    # Gym reset service client:
    rospy.wait_for_service("/pedsim_simulator/gym_reset", timeout=3)
    gym_reset = rospy.ServiceProxy("/pedsim_simulator/gym_reset", GymReset)
    # Gazebo world info service client: gym_reset
    rospy.wait_for_service("/gazebo/get_world_properties", timeout=3)
    get_gazebo_world_info = rospy.ServiceProxy("/gazebo/get_world_properties", GetWorldProperties)
    world_info = get_gazebo_world_info()
    actors_list = [actor_name for actor_name in world_info.model_names if "actor" in actor_name]

    # Testcase humans number problem handling
    if args.use_testcase and len(actors_list) != args.num_agents:
        rospy.logerr("Testcase humans number and humans number on current gazebo are not matched.")
        exit(-1)
    elif args.use_testcase and (args.testcase <= 0 or args.testcase > 500):
        rospy.logerr("Testcase:{} is out of range.".format(args.testcase))
        exit(-1)

    if args.use_testcase:
        # Find csv file
        rospack = rospkg.RosPack()
        gym_config_filepath = os.path.join(rospack.get_path("pedsim_simulator"),
                                       "scenarios/gym_env_config",
                                       "testcases_{}_humans.csv".format(args.num_agents))
        # Check if the test case file exists or not
        if not os.path.isfile(gym_config_filepath):
            rospy.logerr("file: {} is not existed".format(gym_config_filepath))
            exit(-1)

        # Read testcase from csv file
        testcase_dict = {}
        with open(gym_config_filepath, newline='') as csvfile:
            rows = list(csv.reader(csvfile, delimiter=','))
            header_row = rows[0]
            target_row = rows[args.testcase]
            for idx in range(len(target_row)):
                if target_row[idx] != "":
                    testcase_dict[header_row[idx]] = float(target_row[idx])
            # print(testcase_dict)

        # Set ROS parameter: testcase
        rospy.set_param('/walker/testcase', args.testcase)

        req = GymResetRequest()
        for idx in range(args.num_agents):
            init_pose2d = Pose2D(x=testcase_dict['px{}'.format(idx + 1)],
                                 y=testcase_dict['py{}'.format(idx + 1)],
                                 theta=0)
            wp1 = Pose2D(x=testcase_dict['gx{}'.format(idx + 1)],
                         y=testcase_dict['gy{}'.format(idx + 1)],
                         theta=0)
            init_pose2d.theta = np.arctan2(wp1.y - init_pose2d.y,
                                           wp1.x - init_pose2d.x)
            agent_info = GymAgentInfo(init_pose2d=init_pose2d, waypoints_list=[wp1])
            req.agents_list.append(agent_info)
        gym_reset(req)

    else:
        # Set ROS parameter: testcase
        rospy.set_param('/walker/testcase', 0)

        # Randomly generate human's position and waypoint
        all_wp_list = []
        all_wp_list.append(Pose2D(x=MOVING_DISTANCE, y=0, theta=0))     # add robot destination first
        req = GymResetRequest()
        for i in range(args.num_agents):
            # Randomize the pedestrian's angle
            theta = np.random.rand() * np.pi * 2
            init_pose2d = Pose2D(x=np.cos(theta) * MOVING_DISTANCE,
                                 y=np.sin(theta) * MOVING_DISTANCE,
                                 theta=theta - np.pi)
            wp1 = Pose2D(x=np.cos(theta - np.pi) * MOVING_DISTANCE,
                         y=np.sin(theta - np.pi) * MOVING_DISTANCE,
                         theta=theta - np.pi)
            # If waypoints are overlapping, re-generate a new position
            while True:
                flag_collision = False
                for other_wp in all_wp_list:
                    if np.hypot(wp1.x - other_wp.x, wp1.y - other_wp.y) < 1.0:
                        flag_collision = True
                        break
                if not flag_collision: break
                else:
                    theta = np.random.rand() * np.pi * 2
                    init_pose2d = Pose2D(x=np.cos(theta) * MOVING_DISTANCE,
                                         y=np.sin(theta) * MOVING_DISTANCE,
                                         theta=theta - np.pi)
                    wp1 = Pose2D(x=np.cos(theta - np.pi) * MOVING_DISTANCE,
                                 y=np.sin(theta - np.pi) * MOVING_DISTANCE,
                                 theta=theta - np.pi)
            all_wp_list.append(wp1)

            agent_info = GymAgentInfo(init_pose2d=init_pose2d, waypoints_list=[wp1])
            req.agents_list.append(agent_info)
        gym_reset(req)


#!/usr/bin/env python
from pstudio import AE, set_output
import numpy as np
import matplotlib.pyplot as plt
from math import pi

set_output('-')
#ae = AE('H', xcname='LDA', relativity='NR', config='1s1')
#ae = AE('Li', xcname='LDA', relativity='NR')
#ae = AE('Cl', xcname='LDA', relativity='SR')
#ae = AE('Ti', xcname='LDA', relativity='NR', config='[Ar] 3d2 4s1', rmin=1e-4)
ae = AE('Ti', xcname='LDA-py', relativity='SR')

try:
    ae.run(verbose=True)
except RuntimeError as err:
    print(err)

r = ae.rgd.r

# plot density
plt.figure()
plt.plot(r, ae.n*r*r, label='density')
plt.xlim(0,20)
plt.legend()
plt.show(block=False)

# plot the potential
plt.figure()
plt.plot(r, ae.vtot, label='Vtot')
plt.plot(r, ae.vion, label='Vion', linestyle='dashed')
plt.xlim(0,20)
plt.ylim(-10,0)
plt.legend()
plt.show(block=False)

plt.figure()
plt.plot(r, ae.vxc*r, label='Vxc*r')
plt.xlim(0,20)
plt.legend()
plt.show(block=False)

# plot orbitals
plt.figure()
for orb in ae.orbitals:
    plt.plot(r, orb.ur, label='n={0},l={1}'.format(orb.n,orb.l))
plt.xlim(0,10)
plt.legend()
plt.show()

quit()


#Recall in Worked Example 5.2.5 that we showed you the code
#for two versions of binary_search: one using recursion, one
#using loops. For this problem, use the recursive one.
#
#In this problem, we want to implement a new version of
#binary_search, called binary_search_year. binary_search_year
#will take in two parameters: a list of instances of Date,
#and a year as an integer. It will return True if any date
#in the list occurred within that year, False if not.
#
#For example, imagine if listOfDates had three instances of
#date: one for January 1st 2016, one for January 1st 2017,
#and one for January 1st 2018. Then:
#
#  binary_search_year(listOfDates, 2016) -> True
#  binary_search_year(listOfDates, 2015) -> False
#
#You should not assume that the list is pre-sorted, but you
#should know that the sort() method works on lists of dates.
#
#Instances of the Date class have three attributes: year,
#month, and day. You can access them directly, you don't
#have to use getters (e.g. myDate.month will access the
#month of myDate).
#
#You may copy the code from Worked Example 5.2.5 and modify
#it instead of starting from scratch. You must implement
#binary_search_year recursively.
#
#Don't move this line:
from datetime import date

#Write your code here!

def binary_search_year(dates, year):
    dates.sort()
    #print("First entry")
    #print (f"My sorted array is {dates} \n")

    midDate = dates[len(dates)//2]
    #print (f"My midDate is {midDate}\n")

    if year == midDate.year:
        #print(f"Match found return True\n")
        return True
    elif year > midDate.year:
        start_index = dates.index(midDate)
        end_index = len(dates)
        if end_index == 0:
            #print(f"I am returning False from greater check\n")
            return False
        greater_arr = dates[start_index:end_index]
        #print(f"greater function {start_index} {end_index}\n")
        #print(f"My greater array is {greater_arr}\n")
        #print("Calling again from greater")
        return binary_search_year(greater_arr, year)
    else:
        start_index = 0
        end_index = dates.index(midDate)
        if end_index == 1:
            #print(f"I am returning False from lesser check\n")
            return False
        lesser_arr = dates[start_index:end_index+1]
        #print(f"lesser function {start_index} {end_index}\n")
        #print(f"My lesser array is {lesser_arr}\n")
        #print("Calling again from lesser")
        return binary_search_year(lesser_arr, year)

#Below are some lines of code that will test your function.
#You can change the value of the variable(s) to test your
#function with different inputs.
#
#If your function works correctly, this will originally
#print: True, then False
listOfDates = [date(2016, 11, 26), date(2014, 11, 29),
               date(2008, 11, 29), date(2000, 11, 25),
               date(1999, 11, 27), date(1998, 11, 28),
               date(1990, 12, 1), date(1989, 12, 2),
               date(1985, 11, 30)]

print(binary_search_year(listOfDates, 2016))
print(binary_search_year(listOfDates, 2007))


"""add x and y

Revision ID: 3555f61aaa79
Revises: 79972ec5f79d
Create Date: 2023-06-22 15:03:27.338959

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = "3555f61aaa79"
down_revision = "79972ec5f79d"
branch_labels = None
depends_on = None

def upgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column("hero", sa.Column("x", sa.Integer(), nullable=False))
    op.add_column("hero", sa.Column("y", sa.Integer(), nullable=False))
    # ### end Alembic commands ###
    # generate_er_diagram(f'migrations/versions/{revision}_er_diagram.png')
    # generate_er_markdown(f'migrations/versions/{revision}_er_diagram.md', f'migrations/versions/er_diagram_{revision}.png')

def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_column("hero", "y")
    op.drop_column("hero", "x")
    # ### end Alembic commands ###


from bottle import route, run, HTTPError, request, HTTPResponse
import album

"""
Requirements:
    1. Веб-сервер принимает GET-запросы по адресу /albums/<artist> и выводит на экран
    сообщение с количеством альбомов исполнителя artist и списком названий этих альбомов.

    2. Веб-сервер принимает POST-запросы по адресу /albums/ и сохраняет переданные пользователем
    данные об альбоме. Данные передаются в формате веб-формы. Если пользователь пытается передать
    данные об альбоме, который уже есть в базе данных, обработчик запроса отвечает
    HTTP-ошибкой 409 и выводит соответствующее сообщение.

    3. Набор полей в передаваемых данных полностью соответствует схеме таблицы album базы данных.

    [id:INTEGER, year:INTEGER, artist:TEXT, genre:TEXT, album:TEXT]

    4. В качестве исходной базы данных использовать файл albums.sqlite3.

    5. До попытки сохранить переданные пользователем данные, нужно провалидировать их.
    Проверить, например, что в поле "год выпуска" передан действительно год.
"""

def valid_data(album_data):
    """
    Description:
        Получает словарь album, который проверяет на наличие всех полей из списка required_items, а также на соответствие некоторым проверкам на валидность вводимой информации. Подведёт словарь к некоторому стандарту и возвратит его в случае успешных проверок. Иначе - вернёт текст ошибки.

    Returns:
        Возвратит раскрытый список: результат в виде булевого значения; значение ошибки / валидный словарь.
    """
    for item in album.required_items:
        if not album_data.get(item):
            return False, 'Missing attribute "%s".' % item
    try:
        album_data["year"] = int(album_data["year"])
    except ValueError:
        return False, 'Incorrect "year" attribute (not a number).'
    else:
        if album_data["year"] < 1860 or album_data["year"] > 2020:
            return False, 'Incorrect "year" attribute (it can\'t be real).'

    for item in album_data:
        # some editing here...
        pass
        # if item != "year":
        #     album_data[item] = str(album_data[item])
    return True, album_data

@route('/albums/<artist>')
def get_albums(artist):
    """
    Description:
        Возвратит строку с заголовком, а также нумерованый список альбомов (при наличии).
        Если альбомов исполнителя нет в базе - веведет 404 с соответствующим сообщением.
    """
    album_list = album.find(artist)
    if not album_list:
        return HTTPError(404, "There are no %s albums in the database." % artist)

    header = "
%s albums [%d]:
" % (album_list[0].artist, len(album_list)) # album_list[0].artist -- берём оригинальное имя из базы, с учётом заглавных букв
    album_names = ["{} ({})".format(album.album, album.year) for album in album_list]
    list_elements = ["
%s

" % name for name in album_names]
    albums_html = "

\n" + '\n'.join(list_elements) + "
"
    return header + albums_html

@route('/albums/', method = "POST")
def add_album():
    """
    Description:
        Обрабатывает POST-запросы на добавление альбома по адресу HOSTPORT/albums/.
        Параметры запроса считываются из полей передаваемой формы. Если введённые параметры
        не пройдут валидацию - вернёт ошибку 404 с указанием причины. Если данный альбом
        уже находится в базе (совпатают поля исполнителя, года и названия) - ответит
        ошибкой 409 с указанием причины.
    """
    album_data = {}
    for item in album.required_items:
        album_data[item] = request.forms.get(item)
    valid, data = valid_data(album_data)
    if not valid:
        return HTTPResponse(data, 400)
    if album.album_exists(data):
        return HTTPResponse("This album is already in the database.", 409)
    else:
        album.add(data)
        return "Database updated."

if __name__ == "__main__":
    run(host = "localhost", port = 8080, debug = True)


from datetime import datetime

# datetime object containing current date and time
now = datetime.now()

print("now =", now)

# dd/mm/YY H:M:S
dt_string = now.strftime("%d/%m/%Y %H:%M:%S")
print("date and time =", dt_string)


from flask_restful import Resource, reqparse
from utils.param_check import check_params
from database.db_ops_get_meas import DB_Ops_Get_Measurements

class GetMeasurements(Resource):
    def __init__(self):
        self.reqparser = reqparse.RequestParser()
        self.reqparser.add_argument('db_name', type=str, help='Name of the database')
        self.get_meas = DB_Ops_Get_Measurements()
        super(GetMeasurements, self).__init__()

    def get(self):
        args = self.reqparser.parse_args()
        params_check_result = check_params(['db_name'], args)
        if params_check_result[0] is False:
            return params_check_result[1]

        db_name = args['db_name']
        result = self.get_meas.get_measurements(db_name)

        return result


import numpy as np
np.random.seed(333)
from keras import models
from keras import layers
import matplotlib.pyplot as plt
from keras.optimizers import Adam
from keras import regularizers
import keras_metrics
from Cardio_Data import Histogram as hist
from sklearn.model_selection import train_test_split

def main():
    train_x, train_y, test_x, test_y= load_data()
    # Get the result for linear perceptron
    epoch = 50
    batch_size = 2000

    # Get the result for MLP
    result_mlp, mlp_weights = MLP(train_x, train_y, test_x, test_y, epoch, batch_size)

    #save('lp_weights_data', lp_weights)
    #save('mlp_weights_data', mlp_weights)

    # Show the result
    show_result(result_mlp)

def load_data():
    dataset, x, y = hist.load_newdata()
    train_x, test_x, train_y, test_y = train_test_split(x, y, random_state=42)

    return train_x, train_y, test_x, test_y

def MLP(train_x, train_y, test_x, test_y, epoch, batch_size):
    # One hidden layer with 60 neurons
    model = models.Sequential()
    layer = layers.Dense(200, activation="relu", input_shape=(train_x.shape[1],),kernel_regularizer=regularizers.l2(1e-10),activity_regularizer=regularizers.l1(1e-10))
    model.add(layer)
    model.add(layers.Dropout(0.1, noise_shape=None, seed=None))
    #model.add(layers.Dropout(0.2, noise_shape=None, seed=None))
    model.add(layers.Dense(100, activation="relu",kernel_regularizer=regularizers.l2(1e-10),activity_regularizer=regularizers.l1(1e-10)))
    model.add(layers.Dropout(0.1, noise_shape=None, seed=None))
    model.add(layers.Dense(60, activation="relu", kernel_regularizer=regularizers.l2(1e-10),
                           activity_regularizer=regularizers.l1(1e-10)))
    model.add(layers.Dense(30, activation="relu", kernel_regularizer=regularizers.l2(1e-10),
                           activity_regularizer=regularizers.l1(1e-10)))
    #model.add(layers.Dropout(0.1, noise_shape=None, seed=None))
    model.add(layers.Dense(10, activation="relu",kernel_regularizer=regularizers.l2(1e-10),activity_regularizer=regularizers.l1(1e-10)))
    model.add(layers.Dense(1, activation="sigmoid"))
    model.summary()
    adam = Adam(lr=0.0001, beta_1=0.9, beta_2=0.999, epsilon=None, decay=0.0, amsgrad=False)
    model.compile(loss='binary_crossentropy', metrics=['accuracy', keras_metrics.precision(), keras_metrics.recall()],optimizer=adam)

# Get the loss and accuracy by using cross validation
    results_mlp = model.fit(train_x, train_y, epochs=epoch, batch_size= batch_size, validation_data=(test_x, test_y))
    #predict_label = model.predict_classes(train_x)
    weights_mlp = layer.get_weights()
    return results_mlp,weights_mlp

def show_result(result_lp):
    result = result_lp.history
    result.keys()  # dict_keys(['val_loss', 'val_acc', 'val_precision', 'val_recall', 'loss', 'acc', 'precision', 'recall'])
    # train_loss = result['loss']
    # train_loss.insert(0,0)

    # val_loss = result['val_loss']
    # val_loss.insert(0,0)
    # Accuracy
    train_acc = result['acc']
    train_acc.insert(0, 0)
    val_acc = result['val_acc']
    val_acc.insert(0, 0)
    epochs = range(0, len(val_acc))

    # precision
    train_pre = result['precision']
    train_pre.insert(0, 0)
    val_pre = result['val_precision']
    val_pre.insert(0, 0)

    # recall
    train_recall = result['recall']
    train_recall.insert(0, 0)
    val_recall = result['val_recall']
    val_recall.insert(0, 0)

    plt.title("MLP Classifier")
    plt.subplot(3, 1, 2)
    plt.plot(epochs, train_pre, 'r', label='Train Precision')
    plt.plot(epochs, val_pre, 'b', label="Test Precision")
    plt.xlabel('Epochs')
    plt.ylabel('Precision')
    plt.grid(True)

    plt.subplot(3, 1, 3)

    plt.plot(epochs, train_recall, 'r', label='Train Recall')
    plt.plot(epochs, val_recall, 'b', label="Test Recall")
    plt.xlabel('Epochs')
    plt.ylabel('Recall')
    plt.grid(True)

    plt.subplot(3, 1, 1)
    # plt.plot(epochs, train_loss, 'green', label = 'Training loss')
    # plt.plot(epochs, val_loss, 'yellow', label = "Validation loss")
    plt.plot(epochs, train_acc, 'r', label='Train Accuracy')
    plt.plot(epochs, val_acc, 'b', label="Test Accuracy")
    plt.xlabel('Epochs')
    plt.ylabel('Accuracy')
    plt.grid(True)
    # plt.legend()
    # plt.show()
    # plt.savefig()

    # plt.subplots_adjust(bottom=0.25, top=0.75)
    plt.show()

main()


import logging
from abc import ABCMeta, abstractmethod
from typing import List, Tuple, Optional, Union, Iterable

from messageflux.iodevices.base import InputDevice, OutputDeviceManager, ReadResult, InputDeviceManager
from messageflux.iodevices.base.common import MessageBundle, Message
from messageflux.message_handling_service import MessageHandlingServiceBase

_logger = logging.getLogger(__name__)

class PipelineResult:
    """
    a result from pipeline handler
    """

    def __init__(self,
                 output_device_name: str,
                 message_bundle: Union[MessageBundle, Message]):
        self.output_device_name = output_device_name
        if isinstance(message_bundle, Message):
            message_bundle = MessageBundle(message=message_bundle)

        self.message_bundle = message_bundle

class PipelineHandlerBase(metaclass=ABCMeta):
    """
    a pipeline handler base class. used to handle a single message that passes through the pipeline
    """

    def prepare(self):
        """
        called when the service starts.
        can be overrided by child class to perform some initialization logic
        """
        pass

    def shutdown(self):
        """
        called when the service stops.
        can be overrided by child class to perform some cleanup logic
        """
        pass

    @abstractmethod
    def handle_message(self,
                       input_device: InputDevice,
                       message_bundle: MessageBundle) -> Optional[Union[PipelineResult, Iterable[PipelineResult]]]:
        """
        Handles a message from an input device. and returns a tuple of the output device name, message and headers to
        send to.

        :param input_device: The input device that sent the message.
        :param message_bundle: The message that was received.

        :return: None if the message should not be sent to any output device.
        PipelineResult (or iterable of) if messages should be sent to the output device with the given name.
        """
        pass

class FixedRouterPipelineHandler(PipelineHandlerBase):
    """
    A pipeline handler that routes all messages to a single output device. without any processing.
    """

    def __init__(self, output_device_name: str):
        self._output_device_name = output_device_name

    def handle_message(self,
                       input_device: InputDevice,
                       message_bundle: MessageBundle) -> Optional[PipelineResult]:
        """
        routes the message to the fixed output

        :param input_device: The input device that sent the message.
        :param message_bundle: The message that was received.

        :return: a pipeline result that has the input message bundle, and the fixed output device name
        """
        output_message_bundle = MessageBundle(message=message_bundle.message.copy(), device_headers={})
        return PipelineResult(output_device_name=self._output_device_name,
                              message_bundle=output_message_bundle)

class PipelineService(MessageHandlingServiceBase):
    """
    a service that uses a PipelineHandler object to process messages from input, and send to output
    """

    def __init__(self, *,
                 input_device_manager: InputDeviceManager,
                 input_device_names: Union[List[str], str],
                 pipeline_handler: PipelineHandlerBase,
                 output_device_manager: Optional[OutputDeviceManager] = None,
                 **kwargs):
        """

        :param pipeline_handler: the pipeline handler to use for handling the messages
        :param output_device_manager: Optional. the output device manager to send messages to
        :param **kwargs: passed to parent as is
        """
        super().__init__(input_device_manager=input_device_manager,
                         input_device_names=input_device_names,
                         **kwargs)
        self._output_device_manager = output_device_manager
        self._pipeline_handler = pipeline_handler

    def _prepare_service(self):
        super()._prepare_service()
        if self._output_device_manager is not None:
            self._output_device_manager.connect()
        self._pipeline_handler.prepare()

    def _handle_message_batch(self, batch: List[Tuple[InputDevice, ReadResult]]):
        for input_device, read_result in batch:
            pipeline_handler_result = self._pipeline_handler.handle_message(input_device, read_result)
            if pipeline_handler_result is not None:
                if isinstance(pipeline_handler_result, PipelineResult):
                    pipeline_handler_result = [pipeline_handler_result]
                for pipeline_result in pipeline_handler_result:
                    if self._output_device_manager is None:
                        _logger.warning("pipeline handler returned a result to output to device: "
                                        f"'{pipeline_result.output_device_name}', "
                                        f"but no output_device_manager was given")
                        continue

                    output_device = self._output_device_manager.get_output_device(pipeline_result.output_device_name)
                    output_device.send_message(message=pipeline_result.message_bundle.message,
                                               device_headers=pipeline_result.message_bundle.device_headers)

    def _finalize_service(self, exception: Optional[Exception] = None):
        try:
            super()._finalize_service(exception)
        finally:
            if self._output_device_manager is not None:
                self._output_device_manager.disconnect()
            self._pipeline_handler.shutdown()


from unicodedata import name
import matplotlib.pyplot as plt
import numpy as np
import tkinter as tk
from tkinter import filedialog
import csv

def main():
    root = tk.Tk()
    root.withdraw()
    file_path = filedialog.askopenfilename(filetypes=[("CSV", ".csv")])

    # camera index
    cams = {
        'oak-d':0,
        'oak-d-pro':1,
        'orbbec':2,
        'rsd435':3,
        'rsd455':4,
        'zed2':5
    }

    bias = np.zeros([6,7])
    precision = np.zeros([6,7])
    nan_ratio = np.zeros([6,7])
    ep = np.zeros([6,7])    # 1-5 meters + dark + shiny
    nan_edge_ratio = np.zeros([6,7])
    #quad_err = np.zeros([6,7])
    #adr = np.zeros([6,3])
    adp = np.zeros([6,3])                      # 20-60 deg
    rad_mean = np.zeros([6,4])
    rad_std = np.zeros([6,4])
    sphere_err = np.zeros([6,4])     # 1-3 meters + dark

    with open(file_path, newline='') as csvfile:
        reader = csv.reader(csvfile, delimiter=',', quotechar='|')
        #sort results
        for row in reader:
            #skip first row
            if row[0] == 'camera': continue
            # setup 1
            elif row[2] == '1':
                if row[1] == '11': row[1] = '7'
                bias[int(cams[row[0]]),int(row[1])-1] = float(row[3])
                precision[int(cams[row[0]]),int(row[1])-1] = float(row[4])
                nan_ratio[int(cams[row[0]]),int(row[1])-1] = float(row[5])
                r6 = row[6].replace('  ', ' ').replace('  ', ' ').replace('  ', ' ').replace('  ', ' ').replace('  ', ' ').replace('  ', ' ').replace('  ', ' ').replace('[ ', '').replace(' ]', '').replace('[', '').replace(']', '')
                ep[int(cams[row[0]]),int(row[1])-1] = np.mean([float(i) for i in r6.split(' ')])
                nan_edge_ratio[int(cams[row[0]]),int(row[1])-1] = float(row[7])
                #quad_err[int(cams[row[0]]),int(row[1])-1] = float(row[8])
            # setup 2
            elif row[2] == '2':
                adp[int(cams[row[0]]),int(row[1])-12] = float(row[3])/1000
                #std_adr[int(cams[row[0]]),int(row[1])-12] = float(row[4])
            elif row[2] == '3':
                rad_mean[int(cams[row[0]]),int(row[1])-7] = float(row[3])
                rad_std[int(cams[row[0]]),int(row[1])-7] = float(row[4])
                sphere_err[int(cams[row[0]]),int(row[1])-7] = float(row[5])
            else: continue

    plt.figure()
    plt.plot([1,2,3,4,5], bias[0,0:5], 'x-', [1,2,3,4,5], bias[1,0:5], 'x-', [1,2,3,4,5], bias[2,0:5], 'x-', [1,2,3,4,5], bias[3,0:5], 'x-', [1,2,3,4,5], bias[4,0:5], 'x-', [1,2,3,4,5], bias[5,0:5], 'x-')
    plt.legend(['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'])
    plt.xlabel('distance [m]')
    plt.ylabel('bias [m]')

    plt.figure()
    plt.plot([1,2,3,4,5], precision[0,0:5], 'x-', [1,2,3,4,5], precision[1,0:5], 'x-', [1,2,3,4,5], precision[2,0:5], 'x-', [1,2,3,4,5], precision[3,0:5], 'x-', [1,2,3,4,5], precision[4,0:5], 'x-', [1,2,3,4,5], precision[5,0:5], 'x-')
    plt.legend(['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'])
    plt.xlabel('distance [m]')
    plt.ylabel('precision [m]')

    plt.figure()
    plt.plot([1,2,3,4,5], nan_ratio[0,0:5], 'x-', [1,2,3,4,5], nan_ratio[1,0:5], 'x-', [1,2,3,4,5], nan_ratio[2,0:5], 'x-', [1,2,3,4,5], nan_ratio[3,0:5], 'x-', [1,2,3,4,5], nan_ratio[4,0:5], 'x-', [1,2,3,4,5], nan_ratio[5,0:5], 'x-')
    plt.legend(['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'])
    plt.xlabel('distance [m]')
    plt.ylabel('nan-ratio')

    # precision_scaled = np.multiply(precision, nan_ratio) + precision
    # plt.figure()
    # plt.plot([1,2,3,4,5], precision_scaled[0,0:5], [1,2,3,4,5], precision_scaled[1,0:5], [1,2,3,4,5], precision_scaled[2,0:5], [1,2,3,4,5], precision_scaled[3,0:5], [1,2,3,4,5], precision_scaled[4,0:5], [1,2,3,4,5], precision_scaled[5,0:5])
    # plt.legend(['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'])
    # plt.xlabel('distance [m]')
    # plt.ylabel('nan-ratio')

    plt.figure()
    plt.plot([1,2,3,4,5], ep[0,0:5], 'x-', [1,2,3,4,5], ep[1,0:5], 'x-', [1,2,3,4,5], ep[2,0:5], 'x-', [1,2,3,4,5], ep[3,0:5], 'x-', [1,2,3,4,5], ep[4,0:5], 'x-', [1,2,3,4,5], ep[5,0:5], 'x-')
    plt.legend(['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'])
    plt.xlabel('distance [m]')
    plt.ylabel('edge precision [m]')

    # plt.figure()
    # plt.plot([1,2,3,4,5], nan_edge_ratio[0,0:5], [1,2,3,4,5], nan_edge_ratio[1,0:5], [1,2,3,4,5], nan_edge_ratio[2,0:5], [1,2,3,4,5], nan_edge_ratio[3,0:5], [1,2,3,4,5], nan_edge_ratio[4,0:5], [1,2,3,4,5], nan_edge_ratio[5,0:5])
    # plt.legend(['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'])
    # plt.title('NaN-Edge-Ratio')

    # ep_scaled = np.multiply(ep, nan_edge_ratio) + ep
    # plt.figure()
    # plt.plot([1,2,3,4,5], ep_scaled[0,0:5], [1,2,3,4,5], ep_scaled[1,0:5], [1,2,3,4,5], ep_scaled[2,0:5], [1,2,3,4,5], ep_scaled[3,0:5], [1,2,3,4,5], ep_scaled[4,0:5], [1,2,3,4,5], ep_scaled[5,0:5])
    # plt.legend(['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'])
    # plt.title('Scaled Edge Precision')

    # plt.figure()
    # plt.plot([1,2,3,4,5], quad_err[0,0:5], [1,2,3,4,5], quad_err[1,0:5], [1,2,3,4,5], quad_err[2,0:5], [1,2,3,4,5], quad_err[3,0:5], [1,2,3,4,5], quad_err[4,0:5], [1,2,3,4,5], quad_err[5,0:5])
    # plt.legend(['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'])
    # plt.title('Quad Reconstruction Error')

    angles = [0, 20, 40, 60]
    plt.figure()
    data = np.hstack([precision[:,1].reshape(6,1) ,adp[:,0:3]]).T
    plt.plot(angles, data, 'x-')
    plt.legend(['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'])
    plt.xlabel('angle [°]')
    plt.ylabel('angle dependent precision [m]')
    plt.ylim([-0.005, 0.4])
    plt.title('Angle Dependent Precision')

    # plt.figure()
    # plt.plot([1,2,3], rad_mean[0,0:3], [1,2,3], rad_mean[1,0:3], [1,2,3], rad_mean[2,0:3], [1,2,3], rad_mean[3,0:3], [1,2,3], rad_mean[4,0:3], [1,2,3], rad_mean[5,0:3])
    # plt.legend(['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'])
    # plt.title('Radius Reconstruction Error Mean')

    plt.figure()
    plt.plot([1,2,3], sphere_err[2,0:3]/1000, 'x-', [1,2,3], sphere_err[3,0:3]/1000, 'x-', [1,2,3], sphere_err[4,0:3]/1000, 'x-', [1,2,3], sphere_err[5,0:3]/1000, 'x-')
    plt.legend(['Astra Stereo', 'D435', 'D455', 'ZED2'])
    plt.xlabel('distance [m]')
    plt.ylabel('sphere radius mean error [m]')
    # plt.title('Sphere Reconstruction Error')

    plt.figure()
    plt.plot([1,2,3], rad_std[2,0:3], 'x-', [1,2,3], rad_std[3,0:3], 'x-', [1,2,3], rad_std[4,0:3], 'x-', [1,2,3], rad_std[5,0:3], 'x-')
    plt.legend(['Astra Stereo', 'D435', 'D455', 'ZED2'])
    plt.xlabel('distance [m]')
    plt.ylabel('sphere radius standard deviation [m]')
    # plt.title('Sphere Reconstruction Error Standard Deviation')

    reference_data = np.array([bias[:,1], precision[:,1], sphere_err[:,1], rad_std[:,1]])
    low_light_data = np.array([bias[:,5], precision[:,5], sphere_err[:,3], rad_std[:,3]])
    low_light_increase = np.array(((reference_data-low_light_data)/reference_data)*100)
    low_light_increase[2:4, 2] = np.nan # sphere values for orbbec are zero but should be nan

    # plt.figure()
    # plt.plot(['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'], low_light_increase[0,:],'rs',
    #     ['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'], low_light_increase[1,:], 'gs',
    #     ['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'], low_light_increase[2,:],'bs',
    #     ['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'], low_light_increase[3,:], 'cs',
    #     )

    # plt.legend(['bias', 'precision', 'sphere mean', 'sphere std'])
    # plt.ylabel('low light performance [%]')
    # # plt.title('Low Light Perfomance')
    # plt.ylim([-1100, 150])

    reference_data = np.array([bias[:,1], precision[:,1], nan_ratio[:,1], ep[:,1]])
    shiny_data = np.array([bias[:,6], precision[:,6], nan_ratio[:,6], ep[:,6]])
    shiny_data_increase = np.array(((reference_data-shiny_data)/reference_data)*100)
    # low_light_increase[2:4, 2] = np.nan # sphere values for orbbec are zero but should be nan

    # plt.figure()
    # plt.plot(['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'], shiny_data_increase[0,:],'rs',
    #     ['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'], shiny_data_increase[1,:], 'gs',
    #     # ['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'], shiny_data_increase[2,:],'bs',
    #     # ['Oak-D', 'Oak-D Pro', 'Astra Stereo', 'D435', 'D455', 'ZED2'], shiny_data_increase[3,:], 'cs',
    #     )
    # plt.legend(['bias', 'precision'])
    # plt.ylabel('reflection performance [%]')
    # # plt.title('Low Light Perfomance')
    # plt.ylim([-1100, 150])

    plt.show()

    return

if __name__ == "__main__":
    main()


from rest_framework.views import status
from app.api.helpers.constants import (VEHICLE_REGISTRATION_SUCCESS_MESSAGE)
from .base_test import TestBaseCase

class RegisterVehicleTest(TestBaseCase):

    def test_register_vehicle_successeds(self):
        """
        Test schedule route
        """
        response = self.register_vehicle_succeeds()
        self.assertEqual(response.status_code, status.HTTP_201_CREATED)
        self.assertIsInstance(response.data, dict)
        self.assertIn('message', response.data)
        self.assertEqual(response.data['message'],
                        VEHICLE_REGISTRATION_SUCCESS_MESSAGE)


import json
import lib
import os

def RFIHandRangeDecision(hand, position):
    if position == lib.Position.BigBlind.name:
        return True

    f = open("hand-range-charts.json")
    data = json.load(f);
    handRange = data[lib.Action.RFI.name][position];
    hand.sort(key=cardToNumber, reverse=True)

    print(hand)
    for subsetRange in handRange:
        if checkCardInSubsetRange(hand, subsetRange) == True:
            return True
    return False

def aggressorHandRangeDecision(hand, position, action, aggressor):
    f = open("hand-range-charts.json")
    data = json.load(f);
    print(action)
    print(position)
    print(aggressor)
    handRangeChartURL = data[action][position][aggressor];
    os.system("gopen ./preflop-charts/" + handRangeChartURL)

def checkCardInSubsetRange(hand, subsetRange):
    # Example of a subset of range in shortform: A9s+
    if cardToNumber(hand[0]) < rankToNumber(subsetRange[0]):
        return False
    if cardToNumber(hand[1]) < rankToNumber(subsetRange[1]):
        return False

    if subsetRange[2] == 's': #'s' means cards are suited. 'o' is offsuit
        if hand[0]["suit"] == hand[1]["suit"]:
            return True

    if subsetRange[2] == 'o': # 'o' is offsuit
        return True

    if subsetRange[0] == subsetRange[1]: # Dealing with pairs
        if hand[0]["rank"] == hand[1]["rank"]:
            if cardToNumber(hand[0]) >= rankToNumber(subsetRange[0]):
                return True

    return False

def cardToNumber(card):
    return rankToNumber(card["rank"])

def rankToNumber(card):
    if card == 'A':
        return 14
    elif card == 'K':
        return 13
    elif card == 'Q':
        return 12
    elif card == 'J':
        return 11
    elif card == 'T':
        return 10
    else:
        return int(card)


from flask import Blueprint, jsonify, session, request
# from app.models import db, User, Catch, Subpost, Condition
# from app.utils import upload, format_errors
# from sqlalchemy.orm import joinedload
import os

map_routes = Blueprint('map', __name__)
@map_routes.route("/key", methods=["GET"])
def load_map_api_key():
    key = os.environ.get('MAPS_API_KEY')
    return {'googleMapsAPIKey': key}

# @map_routes.route("/key", methods=["GET"])


import nltk
from nltk.stem import WordNetLemmatizer
from nltk.stem import SnowballStemmer
nltk.download('wordnet')
nltk.download('omw-1.4')

class LemmatizerAndStemmer:
    @staticmethod
    def lemmatize_tweet(tweet: str) -> str:
        """
        Lemmatizes a tweet. worst, worse, bad -> bad.
        :param tweet: The tweet to lemmatize.
        :return: The lemmatized tweet.
        """
        lemmatizer = WordNetLemmatizer()
        new_tweet = ""
        for word in tweet.split(' '):
            new_tweet += lemmatizer.lemmatize(word) + ' '
        return new_tweet

    @staticmethod
    def stem_tweet(tweet: str) -> str:
        """
        Stems a tweet. plays, playing -> play.
        :param tweet: The tweet to stem.
        :return: The stemmed tweet.
        """
        ps = SnowballStemmer("english")
        new_tweet = ""
        for word in tweet.split(' '):
            new_tweet += ps.stem(word) + ' '
        return new_tweet

    @staticmethod
    def stem_and_lemmatize_tweet(tweet: str) -> str:
        """
        Stems and lemmatizes a tweet.
        :param tweet: The tweet to stem and lemmatize.
        :return: The stemmed and lemmatized tweet.
        """
        return LemmatizerAndStemmer.lemmatize_tweet(LemmatizerAndStemmer.stem_tweet(tweet))


opc = 0
import numpy as np
import matplotlib.pyplot as plt
import cv2
import base64
from PIL import Image
from io import BytesIO
import argparse
import sys

def letter2ASCII(msg):
     for i in msg:
        yield ord(i)

def encoder(imagen , mensaje, pattern, img=False):

    imagen = cv2.imread(imagen, 1)
    imagen = cv2.cvtColor(imagen, cv2.COLOR_BGR2RGB)

    if img ==False:
        mensaje = open("{}".format(mensaje), "r")
        mensaje = mensaje.read()

    generador = letter2ASCII(mensaje)
    pattern = pattern
    cont = 0
    length = len(mensaje)
    space = (imagen.shape[0] * imagen.shape[1] * 3) - pattern

    if space < length*pattern:
        print('Text too large')
        return 0

    for chn in range(4):
        for row in range(imagen.shape[0]):
            for col in range(imagen.shape[1]):
                cont += 1
                if cont == pattern :
                    cont = 0
                    try:
                        imagen[row][col][chn] = next(generador)
                    except StopIteration:
                        imagen[row][col][chn] = 0
                        name = input('    Name to save new image: ')
                        cv2.imwrite('{}'.format(name),cv2.cvtColor(imagen, cv2.COLOR_BGR2RGB))
                        print('\n')
                        print('------- Image Encoded :) --------')
                        print('\n')
                        print('\n')
                        return imagen

def decoder(imagen, pattern, img=False):
    imagen = cv2.imread(imagen, 1)
    imagen = cv2.cvtColor(imagen, cv2.COLOR_BGR2RGB)

    pattern = pattern
    message = ''
    cont = 0

    for chn in range(4):
        for row in range(imagen.shape[0]):
            for col in range(imagen.shape[1]):
                cont += 1
                if cont == pattern:
                    cont = 0
                    letra = imagen[row][col][chn]
                    if letra != 0:
                        message = message + chr(letra)
                    else:
                        if img == False:
                            print('\n')
                            print('Msg: ', message)
                            print('\n')
                            print('\n')
                            return message
                        else:
                            return message

if __name__ == '__main__':

    while opc != 5:

        print('\n ------- Menu -------')
        print('1.) Text -> Image')
        print('2.) Image -> Text')
        print('3.) Image into Image')
        print('4.) Image from Image')
        print('5.) Exit')
        print('\n')
        opc = int( input("  Option: ") )

        if opc == 1:
            path = input("\n    Path for image: ")
            msg = input("    .txt file: ")
            patt = int(input("    Pattern: "))
            encoder(path, msg, patt)
        elif opc == 2:
            path = input("\n    Path for image: ")
            patt = int(input("    Pattern: "))
            decoder(path, patt)

        elif opc == 3:

            path = input("\n    Path for base image: ")
            path2 = input("    Path for image to hide: ")
            patt = int(input("    Pattern: "))
            msg = None

            with open("{}".format(path2), "rb") as img_file:
                msg = base64.b64encode(img_file.read())

            msg = msg.decode('utf-8')

            encoder(path, msg, patt, True)

        elif opc == 4:

            path = input("\n    Path for image: ")
            patt = int(input("    Pattern: "))
            data = decoder(path, patt, True)

            im = Image.open(BytesIO(base64.b64decode(data)))
            im.save('imageFromDecoder.png', 'PNG')

            print('\n')
            print('------- Image Decoded :) --------')
            print('\n')
            print('\n')

        elif opc == 5:
            print('\n Bye :(')
            sys.exit()


import numpy as np
from nutils import log, _
import scipy.sparse as sp

from aroma import util

class MetaIntegrand(type):

    def __new__(cls, name, bases, attrs):
        subclass = type.__new__(cls, name, bases, attrs)
        if name != 'Integrand':
            Integrand.subclasses[name] = subclass
        return subclass

class Integrand(metaclass=MetaIntegrand):

    subclasses = {}

    @classmethod
    def accepts(cls, obj):
        return False

    @staticmethod
    def get_subclass(obj):
        for subclass in Integrand.subclasses.values():
            if subclass.accepts(obj):
                return subclass
        return None

    @staticmethod
    def acceptable(obj):
        return isinstance(obj, Integrand) or (Integrand.get_subclass(obj) is not None)

    @staticmethod
    def make(obj):
        if isinstance(obj, Integrand):
            return obj
        if not Integrand.acceptable(obj):
            raise NotImplementedError
        return Integrand.get_subclass(obj)(obj)

    def __init__(self):
        self._properties = {}

    @staticmethod
    def read(group):
        type_ = group.attrs['type']
        subclass = util.find_subclass(Integrand, type_)
        return subclass.read(group)

    def prop(self, *args, **kwargs):
        if args:
            assert all(isinstance(arg, str) for arg in args)
            values = [(self._properties[arg] if arg in self._properties else kwargs[arg]) for arg in args]
            if len(args) == 1:
                return values[0]
            return values
        for key, val in kwargs.items():
            if key not in self._properties:
                self._properties[key] = val
        return self

    def write_props(self, group):
        group = group.require_group('properties')
        for key, value in self._properties.items():
            util.to_dataset(value, group, key)

    def read_props(self, group):
        self._properties = {}
        for key, value in group['properties'].items():
            self._properties[key] = util.from_dataset(value)

    def ensure_shareable(self):
        pass

class ThinWrapperIntegrand(Integrand):

    def __init__(self, obj):
        super().__init__()
        self.obj = obj

    @property
    def ndim(self):
        return len(self.shape)

    @property
    def shape(self):
        return self.obj.shape

    def write(self, group, name):
        sub = group.require_group(name)
        util.to_dataset(self.obj, sub, 'data')
        sub.attrs['type'] = self.__class__.__name__
        self.write_props(sub)
        return sub

    @staticmethod
    def read(group):
        cls = util.find_subclass(ThinWrapperIntegrand, group.attrs['type'])
        retval = cls.__new__(cls)
        retval.obj = util.from_dataset(group['data'])
        retval.read_props(group)
        return retval

class NumpyArrayIntegrand(ThinWrapperIntegrand):

    optimized = True

    @classmethod
    def accepts(cls, obj):
        return isinstance(obj, (np.ndarray,) + util._SCALARS)

    def __init__(self, obj):
        if isinstance(obj, np.ndarray):
            super().__init__(obj)
        else:
            super().__init__(np.array(obj))

    def _contract(self, contraction):
        axes, obj = [], self.obj
        for i, cont in enumerate(contraction):
            if cont is None:
                continue
            assert cont.ndim == 1
            for __ in range(i):
                cont = cont[_,...]
            while cont.ndim < self.ndim:
                cont = cont[...,_]
            obj = obj * cont
            axes.append(i)
        return obj.sum(tuple(axes))

    def get(self, contraction):
        return self._contract(contraction)

    def cache(self, **kwargs):
        return self

    def contract(self, contraction):
        return NumpyArrayIntegrand(self._contract(contraction))

    def project(self, projection):
        obj = self.obj
        s = slice(None)
        for i, p in enumerate(projection):
            if p is None:
                continue
            obj = obj[(s,)*i + (_,s,Ellipsis)]
            obj = obj * p[(_,)*i + (s,s) + (_,) * (self.ndim - i - 1)]
            obj = obj.sum(i+1)
        return NumpyArrayIntegrand(obj)

class ScipyArrayIntegrand(ThinWrapperIntegrand):

    optimized = True

    @classmethod
    def accepts(cls, obj):
        return isinstance(obj, sp.spmatrix)

    def get(self, contraction):
        if all(c is None for c in contraction):
            return self.obj
        ca, cb = contraction
        if ca is None:
            return self.obj.dot(cb)
        elif cb is None:
            return self.obj.T.dot(ca)
        return ca.dot(self.obj.dot(cb.T))

    def cache(self, **kwargs):
        return self

    def contract(self, contraction):
        assert len(contraction) == 2

        ca, cb = contraction
        if ca is None and cb is None:
            return self
        assert ca is None or cb is None

        if ca is None:
            return NumpyArrayIntegrand(self.obj.dot(cb))
        return NumpyArrayIntegrand(self.obj.T.dot(ca))

    def project(self, projection):
        if all(p is None for p in projection):
            return self
        pa, pb = projection
        if pa is None:
            return NumpyArrayIntegrand(self.obj.dot(pb.T))
        elif pb is None:
            return NumpyArrayIntegrand(self.obj.T.dot(pa.T).T)
        return NumpyArrayIntegrand(pa.dot(self.obj.dot(pb.T)))

class COOTensorIntegrand(Integrand):

    optimized = True

    def __init__(self, shape, *args):
        super().__init__()
        assert len(shape) == 3
        assert len(shape) == len(args) - 1
        self.shape = shape
        self.ndim = len(shape)

        nz = np.nonzero(args[-1])
        *indices, self.data = [arg[nz] for arg in args]

        fits = all(np.max(i) <= np.iinfo(np.int32).max for i in indices)
        idx_dtype = np.int32 if fits else np.int64
        indices = tuple(i.astype(idx_dtype, copy=True) for i in indices)
        self.indices = indices

        # TODO: Figure out in advance which assemblers we will need
        self.assemblers = {
            (1,): util.CSRAssembler((shape[0], shape[2]), indices[0], indices[2]),
            (2,): util.CSRAssembler((shape[0], shape[1]), indices[0], indices[1]),
            (1,2): util.VectorAssembler((shape[0],), indices[0])
        }

    def write(self, group, name):
        sub = group.require_group(name)
        datagrp = sub.require_group('data')
        util.to_dataset(self.indices[0], datagrp, 'indices-i')
        util.to_dataset(self.indices[1], datagrp, 'indices-j')
        util.to_dataset(self.indices[2], datagrp, 'indices-k')
        util.to_dataset(self.data, datagrp, 'data')
        datagrp.attrs['shape'] = self.shape
        sub.attrs['type'] = 'COOTensorIntegrand'

        assemblers = datagrp.require_group('assemblers')
        for key, assembler in self.assemblers.items():
            name = ','.join(str(s) for s in key)
            ass_grp = assemblers.require_group(name)
            assembler.write(ass_grp)

        return sub

    @staticmethod
    def read(group):
        datagrp = group['data']
        retval = COOTensorIntegrand.__new__(COOTensorIntegrand)
        retval.indices = datagrp['indices-i'][:], datagrp['indices-j'][:], datagrp['indices-k'][:]
        retval.data = datagrp['data'][:]
        retval.shape = tuple(datagrp.attrs['shape'])

        retval.assemblers = {}
        for key, grp in datagrp['assemblers'].items():
            key = tuple(int(i) for i in key.split(','))
            retval.assemblers[key] = getattr(util, grp.attrs['type']).read(grp)

        return retval

    def ensure_shareable(self):
        self.indices = tuple(util.shared_array(i) for i in self.indices)
        self.data = util.shared_array(self.data)
        for ass in self.assemblers.values():
            ass.ensure_shareable()

    def get(self, contraction):
        retval = self._contract(contraction)
        if not isinstance(retval, COOTensorIntegrand):
            return retval
        return retval.toarray()

    def toarray(self):
        # TODO: This could be more efficient, but this function should never be
        # called in performance-critical code anyway
        # Ravel down to a matrix, convert to scipy, then to numpy, then unravel
        flat_index = np.ravel_multi_index(self.indices[1:], self.shape[1:])
        flat_shape = (self.shape[0], np.product(self.shape[1:]))
        matrix = sp.coo_matrix((self.data, (self.indices[0], flat_index)), shape=flat_shape)
        matrix = matrix.toarray()
        return np.reshape(matrix, self.shape)

    def cache(self, **kwargs):
        return self

    def contract(self, contraction):
        return Integrand.make(self._contract(contraction))

    def _contract(self, contraction):
        if all(c is None for c in contraction):
            return self
        contraction = [(i, c) for i, c in enumerate(contraction) if c is not None]
        axes = tuple(i for i, __ in contraction)
        data = np.copy(self.data)
        for i, c in contraction:
            data *= c[self.indices[i]]
        if axes == (0,1,2):
            return np.sum(data)
        return self.assemblers[axes](data)

    def project(self, projection):
        # TODO: Remove this condition
        assert all(p is not None for p in projection)
        pa, pb, pc = projection
        P, __ = pa.shape
        ass = util.CSRAssembler(self.shape[1:], self.indices[1], self.indices[2])
        ret = np.empty((P, pb.shape[0], pc.shape[0]), self.data.dtype)
        for i in log.iter('index', range(P), length=P):
            data = self.data * pa[i, self.indices[0]]
            mx = ass(data)
            ret[i] = pb.dot(mx.dot(pc.T))
        return NumpyArrayIntegrand(ret)

class LazyIntegral:
    pass

def integrate(*args):
    if all(not isinstance(arg, LazyIntegral) for arg in args):
        return args
    assert all(arg.__class__ == args[0].__class__ for arg in args[1:])
    return args[0].__class__.integrate(*args)


import argparse
from os import listdir, path, remove

import cv2
from PIL import Image

parser = argparse.ArgumentParser(description='Clean corrupted images.')
parser.add_argument('-d', '--dataset', type=str, required=True, help="Pass the input data directory.")
args = parser.parse_args()

input_dir = args.dataset

extensions = (".bmp", ".jpg", ".jpeg", ".png",
                    ".tif", ".tiff",".gif")

def valid_ext(file):
    return any([file.lower().endswith(ext) for ext in extensions])

def remove_imgs():
    """
    For a given input directory,
    reads each file, and deletes invalid images.
    """
    for file in listdir(input_dir):
        img_path = path.join(input_dir, file)

        if valid_ext(file):
            try:
                # check using Image
                img = Image.open(img_path)
                img.verify()

                # check using cv2
                img = cv2.imread(img_path)
                if img is None:
                    remove(img_path)

            except (IOError, SyntaxError) as e:
                remove(img_path)
        else:
            remove(img_path)

if __name__ == "__main__":
    remove_imgs()


# -*- coding: utf-8 -*-
import scrapy
from EnergyParser.items import EnergyparserItem

ZIPCODE = '52001'
class EnergySpider(scrapy.Spider):
    name = 'energy'
    # allowed_domains = ['https://www.ree.es/en/balance-diario/peninsula/2014/01/01/d']
    start_urls = ['https://www.ree.es/en/balance-diario/peninsula/2014/01/01/d/']
    url_template = 'https://www.ree.es/en/balance-diario/peninsula/2014/{:02d}/{:02d}/d/'
    D = 1
    M = 1

    # set custom settings
    custom_settings = {
        'DEPTH_LIMIT': 3,
        'FEED_URI': 'energy_peninsula.csv'
    }

    def parse(self, response):
        for m in range(1, 13):
            for d in range(1, 32):
                NextUrl = self.url_template.format(m, d)
                print(NextUrl, self.D)
                yield response.follow(NextUrl, callback=self.parse_data)

    def parse_data(self, response):
        info = EnergyparserItem()
        info['date'] = response.xpath('//tr[@class="primera"]/th[1]/text()').extract()
        info['demand_bc'] = response.xpath('//tr[@class="datos demandasup even"]/td[1]/text()').extract()
        yield info


"""
IMPORTS
"""
import nltk.data
import random
import tkinter as tk

"""
TEST FILES AND TOKENIZER
"""

tokenizer = nltk.data.load('tokenizers/punkt/english.pickle')
fp = open("test.txt")
data = fp.read()

"""
FUNCTIONS
"""

#Retrieves predictions from trained SVM and trained tokenizer, returns input sentences, labels and confidence levels
def getOutput(data):
    sentences = tokenizer.tokenize(data)
    label_list=[]
    confidence_list=[]
    index = range(len(sentences))
    for i in sentences:

        label_list.append(getLabelSVM(i)[0])
        confidence_list.append(getLabelSVM(i)[1])
    dct = {a: {'sentences': b,'Label':c,'Confidence':d} for a, b, c,d in zip(index,sentences,label_list,confidence_list)}
    return dct

#Outputs the data to the terminal
def printOutput(data):
    dct = getOutput(data)
    for p_id, p_info in dct.items():
        print("\nText ID:", p_id)
        for key in p_info:
            print(key + ':', p_info[key])

#Function to return predictions for displaying in interface
def returnOutput(data):
    dct = getOutput(data)
    output = ""
    for p_id, p_info in dct.items():
        output += "\nText ID: {}\n".format(p_id)
        output += "Text: {}\n".format(p_info['sentences'])
        output+= "Label: {}\n".format(p_info['Label'])
        output+= "Confidence: {}\n".format(p_info['Confidence'])

    return output


from __future__ import print_function
import requests,json

class UrlScan:

    def __init__(self,apikey="",url="",useragent=None,referer=None,public=True):
        assert len(apikey) > 0, "API key must be defined"
        assert len(url) > 0, "Url must be defined"
        assert type(public) == type(True), "Public must be a boolean"
        self.apikey = apikey
        self.url = url
        self.useragent = useragent
        self.referer = referer
        self.public = public
        self.scanid = None

    def submit(self):
        header = {'API-Key':self.apikey}
        req = {"url":self.url}
        if self.useragent is not None:
            req['useragent'] = self.useragent
        if self.public:
            req['public'] = "on"
        if self.referer is not None:
            req['referer'] = self.referer
        s = requests.post("https://urlscan.io/api/v1/scan/",data=req,headers=header)
        if s.status_code == 200:
            self.scanid = json.loads(s.text)['uuid']
            return self.scanid
        else:
            raise Exception('Non-200 respond')

    def checkStatus(self):
        header = {'API-Key':self.apikey}
        if self.scanid is None:
            raise Exception("Scan has not been submitted yet, call submit() first")
        r = requests.get("https://urlscan.io/api/v1/result/%s/" % self.scanid,headers=header)
        if r.status_code == 200:
            return r
        if r.status_code == 404:
            raise Exception("Scan has not completed yet")

    def getResult(self):
        header = {'API-Key':self.apikey}
        if self.scanid is None:
            raise Exception("Scan has not been submitted yet, call submit() first")
        r = requests.get("https://urlscan.io/api/v1/result/%s/" % self.scanid,headers=header)
        json_response = r.json()
        if r.status_code == 404:
            raise Exception("Scan has not completed yet")
        return json_response

    def getDom(self):
        self.checkStatus()
        header = {'API-Key':self.apikey}
        dom = requests.get("https://urlscan.io/dom/%s/" % self.scanid,headers=header)
        if dom.status_code == 200:
            return dom.text
        else:
            raise Exception('Non-200 respond: %s - %s' % dom.status_code,dom.text)

    def getScreenshot(self):
        self.checkStatus()
        header = {'API-Key':self.apikey}
        screen = requests.get("https://urlscan.io/screenshots/%s.png" % self.scanid,headers=header)
        if screen.status_code == 200:
            return screen.content
        else:
            raise Exception('Non-200 respond: %s - %s' % screen.status_code,screen.text)

    def __repr__(self):
        return "<UrlScan(url='%s', useragent='%s', referer='%s', public='%s', scanid='%s'>" % (self.url,self.useragent,self.referer,self.public,self.scanid)