from asyncio import wait_for
import asyncio
from datetime import datetime
from sre_parse import State
import threading
import time
from multiprocessing.connection import wait
import webbrowser

from config import Configurations as Config
import websockets as ws
import json
from StateHandler import States
from variables import reservation_variables
from variables.charger_variables import Charger
from variables.misc_variables import Misc
from variables.reservation_variables import Reservation

from ocpp_messages import OCPPMessages

RESERVATION_VARIABLES = Reservation()
CHARGER_VARIABLES = Charger()

class WebSocket():
    def __init__(self):
        try:
            print("ws_init")
            self._webSocket = None

        except Exception as e:
            self._webSocket = None
            print("ws_init_failed")
            print(str(e))

    def get_status(self):
        return CHARGER_VARIABLES.status

    def is_closed(self):
        return self._webSocket.closed

    def set_websocket(self, websocket):
        self._webSocket = websocket

    async def start_websocket(self):
        """
        It tries to connect to a websocket, if it succeeds it sends a boot notification request.
        :return: The return value is a coroutine object.
        """
        try:
            async with ws.connect(
                Config().getServerAddress(),
                subprotocols=Config().getProtocol(),
                ping_interval=Config().getWebSocketPingInterval(),
                timeout=Config().getWebSocketTimeout()
            ) as webSocketConnection:
                self._webSocket = webSocketConnection
                print("Successfully connected to WebSocket")
                await self.send_boot_notification_req()
                while (True):
                    print("Reading ws")
                    message = await self._webSocket.recv()
                    message_json = json.loads(message)
                    await self.handle_message(message_json)

        except Exception as e:
            CHARGER_VARIABLES.current_state = States.S_NOTAVAILABLE
            print("connect failed")
            print(str(e))

    async def send_message(self, json_formatted_message):
        """
        It sends a message to the websocket

        :param json_formatted_message: The message you want to send to the server
        """
        await self._webSocket.send(json_formatted_message)

    async def send_status_notification(self):
     # Sending a status notification to the server.
        print("Send STATUS notificaition: ")
        msg = [2, "0jdsEnnyo2kpCP8FLfHlNpbvQXosR5ZNlh8v", "StatusNotification", {
            "connectorId": "1",
            "errorCode": "",
            "status": CHARGER_VARIABLES.status
        }]
        print("MESSAGE CREATED")
        msg_send = json.dumps(msg)
        await self._webSocket.send(msg_send)
        print("SENT")

    async def listen_for_response(self):
        """
        It listens for a response from the server and prints it out
        """
        try:
            json_formatted_message = await self._webSocket.recv()
            message = json.loads(json_formatted_message)
            print(message)
            return message
        except Exception as e:
            print(str(e))

    async def handle_message(self, message):
        """
        It checks for a message from the server, if it gets one, it checks the message type and calls
        the appropriate function.
        """

        try:
            print("handle_message: ")
            print(message)

            if message[2] == "ReserveNow":
                await asyncio.gather(self.reserve_now(message))

            elif message[2] == "BootNotification":
                message_str = str(message[3]["status"])
                print("Got boot notification response")
                print("Was: " + message_str)

            elif message[2] == "RemoteStartTransaction":
                await asyncio.gather(self.remote_start_transaction(message))

            elif message[2] == "RemoteStopTransaction":
                await asyncio.gather(self.remote_stop_transaction(message))

            elif message[2] == "DataTransfer":
                print("Recieved Data transfer")

                return await asyncio.gather(self.data_transfer_response(message))

            elif message[2] == "StartTransaction":
                self.transaction_id = 347

            elif message[2] == "NotImplemented":
                print(message[3])

            elif message[2] == "StopTransaction":
                pass

            else:
                print(message)
                print("Could not handle message")
        except Exception as e:
            print(e)
            pass

    def update_charger_variables(self):
        return CHARGER_VARIABLES

    async def get_reservation_info(self):
        return RESERVATION_VARIABLES.is_reserved, CHARGER_VARIABLES.status, RESERVATION_VARIABLES.reservation_id_tag, RESERVATION_VARIABLES.reservation_id, RESERVATION_VARIABLES.reserved_connector

    async def data_transfer_request(self, message_id, message_data):
        """
        The function takes in a message_id and message_data, and then sends a message to the websocket

        :param message_id: The message id of the message you want to respond to
        :param message_data: This is the data that you want to send to the EVSE
        """
        s: str = "{}{}{}{}{}{}{}".format("{\"transactionID\":", self.transaction_id,
                                         ",\"latestMeterValue\":", message_data, ",\"CurrentChargePercentage\":", message_data, "}")
        print(s)
        # msg_id = self.charger_id + "DataTransfer" +

        msg = [2, "0jdsEnnyo2kpCP8FLfHlNpbvQXosR5ZNlh8v", "DataTransfer", {
            "vendorId": "com.flexicharge",
            "messageId": "BootData",
            "data": s
        }]
        msg_send = json.dumps(msg)
        await self.send_message(msg_send)

    # Does not work as of now
    async def data_transfer_response(self, message):
        print("Entered send data transfer response")
        CHARGER_VARIABLES.status = "Rejected"
        try:
            if message[3]["vendorId"] == "com.flexicharge" and message[3]["messageId"] == "BootData":
                parsed_data = json.loads(message[3]["data"])
                CHARGER_VARIABLES.charger_id = parsed_data["chargerId"]
                #CHARGER_VARIABLES.charging_price = float(parsed_data["chargingPrice"])
                print("Charger ID is set to: " +
                      str(CHARGER_VARIABLES.charger_id))
                #print("Charging price was set to: "+ str(CHARGER_VARIABLES.charging_price) )
                CHARGER_VARIABLES.status = "Accepted"
                print("CHARGER STATUS IS " + CHARGER_VARIABLES.status)
        except Exception as e:
            print("CHARGER ID: ", str(CHARGER_VARIABLES.get_charger_id()))
            print(str(e))
        try:
            # Send a conf
            conf_msg = [3,
                        message[1],
                        "DataTransfer",
                        {"status": str(CHARGER_VARIABLES.status)}]
            conf_send = json.dumps(conf_msg)
            print("Sending confirmation: " + conf_send)
            CHARGER_VARIABLES.current_state = States.S_AVAILABLE
        except Exception as e:
            print(str(e))

        print("message sent" + str(CHARGER_VARIABLES.current_state))
        await self.send_message(conf_send)

####################Start/Stop Transaction####################
#                 Page 39 in the OCPP Manual                 #

    async def start_transaction(self, is_remote):
        """
        If the charging is remote, then the charging has already started in the remote_start_transaction
        function. Notify the server here

        :param is_remote: True if the charging was started remotely, False if it was started locally
        """
        current_time = datetime.now()
        timestamp = current_time.timestamp()

        if is_remote == True:
            # If remote then charging have started in remote_start_transaction. Notify server here.
            msg = [2, "0jdsEnnyo2kpCP8FLfHlNpbvQXosR5ZNlh8v", "StartTransaction", {
                "connectorId": "1",
                "id_tag": CHARGER_VARIABLES.charging_id_tag,
                "meterStart": CHARGER_VARIABLES.meter_value_total,
                "timestamp": timestamp,
                "reservationId": RESERVATION_VARIABLES.reservation_id,
            }]

            await self.hard_reset_reservation()
            msg_send = json.dumps(msg)
            await self.send_message(msg_send)
        else:  # No reservation
            self.start_charging(self.hardcoded_connector_id,
                                self.hardcoded_id_tag)

            msg = [2, "0jdsEnnyo2kpCP8FLfHlNpbvQXosR5ZNlh8v", "StartTransaction", {
                "connectorId": CHARGER_VARIABLES.charging_connector,
                "id_tag": CHARGER_VARIABLES.charging_id_tag,
                "meterStart": CHARGER_VARIABLES.meter_value_total,
                "timestamp": timestamp,
                "reservationId": None,  # If here, no reservation was made
            }]

            msg_send = json.dumps(msg)
            await self.send_message(msg_send)
        pass

    async def stop_transaction(self, is_remote):
        """
        It stops the transaction and sends a message to the server.

        :param is_remote: Boolean
        """
        current_time = datetime.now()
        timestamp = current_time.timestamp()
        CHARGER_VARIABLES.status = "Available"
        await asyncio.gather(self.send_status_notification())
        if is_remote == True:
            msg = [2, "0jdsEnnyo2kpCP8FLfHlNpbvQXosR5ZNlh8v", "StopTransaction", {
                "idTag": CHARGER_VARIABLES.charging_id_tag,
                "meterStop": CHARGER_VARIABLES.meter_value_total,
                "timestamp": timestamp,
                "transactionId": 1,  # This is hardcoded to work with the mock server change to var
                "reason": "Remote",
                "transactionData": None  # [
                # {
                # Can place timestamp here. (Optional)
                # },
                # Can place meterValues here. (Optional)
                # ]
            }]
            msg_send = json.dumps(msg)
           # if CHARGER_VARIABLES.current_charging_percentage >= 100:
           #     CHARGER_VARIABLES.current_state = States.S_BATTERYFULL
            await self.send_message(msg_send)
            await self.hard_reset_charging()
        else:
            msg = [2, "0jdsEnnyo2kpCP8FLfHlNpbvQXosR5ZNlh8v", "StopTransaction", {
                "idTag": CHARGER_VARIABLES.charging_id_tag,
                "meterStop": CHARGER_VARIABLES.meter_value_total,
                "timestamp": timestamp,
                "transactionId": self.transaction_id,
                "reason": "Remote",
                "transactionData": None  # [
                # {
                # Can place timestamp here. (Optional)
                # },
                # Can place meterValues here. (Optional)
                # ]
            }]
            msg_send = json.dumps(msg)
            await self.send_message(msg_send)
            await self.hard_reset_charging()

       #print("Before recv")
       #response = await self._webSocket.recv() #This is a troublemaker
       #print("After recv")
       #print(json.loads(response))

    async def remote_stop_transaction(self, message):
        """
        If the charging is true and the local transaction id is equal to the transaction id, then print
        "Remote stop charging" and send a message to the server.

        :param message: The message received from the server
        """
        local_transaction_id = message[3]["transactionID"]
        # and int(local_transaction_id) == int(self.transaction_id):
        if CHARGER_VARIABLES.is_charging == True:
            print("Remote stop charging")
            msg = [3,
                   # Have to use the unique message id received from server
                   message[1],
                   "RemoteStopTransaction",
                   {"status": "Accepted"}
                   ]
            msg_send = json.dumps(msg)
            await self.send_message(msg_send)
            # Stop transaction and inform server
            await self.stop_transaction(is_remote=True)
        else:
            print("Charging cannot be stopped")
            msg = [3,
                   # Have to use the unique message id received from server
                   message[1],
                   "RemoteStopTransaction",
                   {"status": "Rejected"}
                   ]
            msg_send = json.dumps(msg)
            await self.send_message(msg_send)

    async def remote_start_transaction(self, message):
        """
        If the idTag has a reservation, start charging from the reservation, set the state to charging,
        send a response to the central system, start the transaction, set the status to charging, and
        send a status notification to the central system.

        :param message: [3, "Unique message id", "RemoteStartTransaction", {"idTag": "12345"}]
        """

        # If the idTag has a reservation
        if int(message[3]["idTag"]) == RESERVATION_VARIABLES.reservation_id_tag:
            print("Remote transaction started")
            # state.set_state(States.S_CHARGING)
            try:
                confirmation_msg = [3,
                                    message[1],  # Unique message id
                                    "RemoteStartTransaction",
                                    {"status": "Accepted"}
                                    ]
                confirmation_msg_json = json.dumps(confirmation_msg)
                print("SENDING RESERVATION MESSAGE ......")

                await self.send_message(confirmation_msg_json)
                print("SENT MESSAGE")
            except Exception as e:
                print(e)
            await self.start_transaction(is_remote=True)
            print("REMOTE START MESSAGE SENT!")
            CHARGER_VARIABLES.status = "Charging"
            # Notify central system that connector is now available
            print("SENDING STATUS NOTIFICATION")
            await self.send_status_notification()
            print("STATUS NOTIFICATION SENT")
            print("Charge should be started")
            CHARGER_VARIABLES.current_state = States.S_CHARGING

        else:  # A non reserved tag tries to use the connector
            print("This tag does not have a reservation")
            confirmation_msg = [3,
                                message[1],  # Unique message id
                                "RemoteStartTransaction",
                                {"status": "Rejected"}
                                ]
            confirmation_msg_json = json.dumps(confirmation_msg)
            await self.send_message(confirmation_msg_json)

##############################################################

    async def reserve_now(self, message):
        local_reservation_id = message[3]["reservationID"]
        local_connector_id = message[3]["connectorID"]
        if RESERVATION_VARIABLES.reservation_id == None or RESERVATION_VARIABLES.reservation_id == local_reservation_id:
            if RESERVATION_VARIABLES.reserved_connector == False and local_connector_id == 0:
                print("Connector zero not allowed")
                msg = [3,
                       # Have to use the unique message id received from server
                       message[1],
                       "ReserveNow",
                       {"status": "Rejected"}
                       ]
                msg_send = json.dumps(msg)
                await self.send_message(msg_send)
                return
            await self.hard_reset_reservation()
            RESERVATION_VARIABLES.is_reserved = True
            CHARGER_VARIABLES.status = "Reserved"
            await asyncio.gather(self.send_status_notification())
            # state.set_state(States.S_FLEXICHARGEAPP)
            RESERVATION_VARIABLES.reservation_id_tag = int(message[3]["idTag"])
            RESERVATION_VARIABLES.reservation_id = message[3]["reservationID"]
            RESERVATION_VARIABLES.reserved_connector = message[3]["connectorID"]
            timestamp = message[3]["expiryDate"]  # Given in ms since epoch

            msg = [3,
                   # Have to use the unique message id received from server
                   message[1],
                   "ReserveNow",
                   {"status": "Accepted"}
                   ]
            msg_send = json.dumps(msg)
            await self.send_message(msg_send)
            CHARGER_VARIABLES.current_state = States.S_FLEXICHARGEAPP
        elif RESERVATION_VARIABLES.reserved_connector == local_connector_id:
            print("Connector occupied")
            msg = [3,
                   # Have to use the unique message id received from server
                   message[1],
                   "ReserveNow",
                   {"status": "Occupied"}
                   ]
            msg_send = json.dumps(msg)
            await self.send_message(msg_send)
        else:
            print("Implement other messages for non accepted reservations")
            msg = [3,
                   # Have to use the unique message id received from server
                   message[1],
                   "ReserveNow",
                   {"status": "Occupied"}
                   ]
            msg_send = json.dumps(msg)
            await self.send_message(msg_send)

    async def send_boot_notification_req(self):
        msg = [2, "0jdsEnnyo2kpCP8FLfHlNpbvQXosR5ZNlh8v", "BootNotification", {
            "chargePointVendor": "AVT-Company",
            "chargePointModel": "AVT-Express",
            "chargePointSerialNumber": "avt.001.13.1",
            "chargeBoxSerialNumber": "avt.001.13.1.01",
            "firmwareVersion": "0.9.87",
            "iccid": "",
            "imsi": "",
            "meterType": "AVT NQC-ACDC",
            "meterSerialNumber": "avt.001.13.1.01"}]
        msg_send = json.dumps(msg)
        print("Sending boot notification")
        await self.send_message(msg_send)

    async def send_boot_notification_conf(self, message):
        conf_msg = [3,
                    message[1],
                    "DataTransfer",
                    {"status": "Accepted"}]
        conf_send = json.dumps(conf_msg)
        print("Sending confirmation: " + conf_send)
        try:
            await self.send_message(conf_send)
            print("Message went away")
        except Exception as e:
            print(str(e))

    async def start_charging_from_reservation(self):
        pass

    async def hard_reset_charging(self):
        pass

    async def hard_reset_reservation(self):
        pass

    async def send_periodic_meter_values(self):
        """
        It sends the current charging percentage to the server every 2 seconds, and if the car is
        charging, it starts the function again
        """
       #asyncio.run(self.send_data_transfer(1, self.charger.current_charging_percentage))
       #
       # if self.charger.current_charging_percentage:
       #    threading.Timer(2, self.send_periodic_meter_values).start()

       #msg_send = json.dumps(msg)
       # await self.my_websocket.send(msg_send)

    async def send_heartbeat(self):
        """
        It sends a heartbeat message to the websocket server
        """
        msg = [2, "0jdsEnnyo2kpCP8FLfHlNpbvQXosR5ZNlh8v", "Heartbeat", {}]
        msg_send = json.dumps(msg)
        await self._webSocket.send(msg_send)
        # print(await self.webSocket.recv())
        # await asyncio.sleep(1)
        self.timestamp_at_last_heartbeat = time.perf_counter()

    async def check_if_time_for_heartbeat(self):
        """
        If the time since the last heartbeat is greater than or equal to the time between heartbeats,
        return True. Otherwise, return False.
        :return: a boolean value.
        """
        seconds_since_last_heartbeat = time.perf_counter() - \
            (self.timestamp_at_last_heartbeat)
        if seconds_since_last_heartbeat >= self.time_between_heartbeats:
            return True
        else:
            return False

    # Depricated in back-end
    async def send_meter_values(self):
        """
        It sends a message to the back-end with the sampled values
        """
        timestamp = int(time.time() * 1000)
        unique_id = str(CHARGER_VARIABLES.charger_id)+ "MeterValues" + str(timestamp)

        message = [2,
                   unique_id,
                   "MeterValues",
                   {
                       "connectorId": 1,
                       "transactionId": 1,
                       "timestamp": timestamp,
                       "values": {
                           "chargingPercent": {
                               "value": CHARGER_VARIABLES.current_charging_percentage,
                               "unit": "%",
                               "measurand": "SoC"

                           },
                           "chargingPower": {
                               "value": "chargingPower",
                               "unit": "W",
                               "measurand": "Power.Active,Import"
                           },
                           "chargedSoFar": {
                               "value": CHARGER_VARIABLES.meter_value_total,
                               "unit": "Wh",
                               "measurand": "Energy.Active.Import"
                           }

                       }
                   }]
        json_formatted_message = json.dumps(message)
        await self.send_message(json_formatted_message)

    async def send_data_reserve(self):
        """
        It sends a message to the server, which is a list of two strings.
        """
        msg = ["chargerplus", "ReserveNow"]
        msg_send = json.dumps(msg)
        await self.send_message(msg_send)

    async def send_data_remote_start(self):
        """
        It sends a message to the websocket server, which then sends a message to the car.
        """
        msg = ["chargerplus", "RemoteStart"]
        msg_send = json.dumps(msg)
        await self.send_message(msg_send)

    async def send_data_remote_stop(self):
        """
        It sends a message to the websocket server to stop the charging session
        """
        msg = ["chargerplus", "RemoteStop"]
        msg_send = json.dumps(msg)
        await self.send_message(msg_send)


from typing import TYPE_CHECKING, Dict, Tuple

from PyQt6.QtWidgets import QGraphicsView
from PyQt6.QtCore import QPointF

from objects.ghosts.ghost_arrow import GhostArrow
from objects.ghosts.ghost_prop import GhostProp
from objects.grid import Grid
from objects.letter_item import LetterItem
from objects.prop.prop_types import *
from constants.string_constants import *
from utilities.TypeChecking.TypeChecking import Colors, Locations, PropTypes
from widgets.option_picker.option.option_view import OptionView

if TYPE_CHECKING:
    from objects.pictograph.pictograph import Pictograph

class OptionInit:
    def __init__(self, pictograph: "Pictograph") -> None:
        self.pictograph = pictograph
        self.main_widget = pictograph.main_widget

    def init_view(self) -> QGraphicsView:
        view = OptionView(self.pictograph)
        return view

    def init_grid(self) -> Grid:
        grid = Grid(self.pictograph)
        grid_position = QPointF(0, 0)
        grid.setPos(grid_position)

        self.pictograph.grid = grid
        return grid

    def init_props(self, prop_type: PropTypes) -> Dict[Colors, Prop]:
        red_prop_Dict = {
            COLOR: RED,
            PROP_TYPE: prop_type,
            LOCATION: NORTH,
            LAYER: 1,
            ORIENTATION: IN,
        }
        blue_prop_Dict = {
            COLOR: BLUE,
            PROP_TYPE: prop_type,
            LOCATION: SOUTH,
            LAYER: 1,
            ORIENTATION: IN,
        }

        prop_class_mapping = {
            STAFF.lower(): Staff,
            BIGSTAFF.lower(): BigStaff,
            CLUB.lower(): Club,
            FAN.lower(): Fan,
            MINIHOOP.lower(): MiniHoop,
            BUUGENG.lower(): Buugeng,
            TRIAD.lower(): Triad,
            BIGTRIAD.lower(): BigTriad,
            BIGHOOP.lower(): BigHoop,
            DOUBLESTAR.lower(): DoubleStar,
            BIGDOUBLESTAR.lower(): BigDoubleStar,
            QUIAD.lower(): Quiad,
            SWORD.lower(): Sword,
            GUITAR.lower(): Guitar,
            UKULELE.lower(): Ukulele,
            CHICKEN.lower(): Chicken,
        }

        prop_class = prop_class_mapping.get(prop_type)
        if prop_class is None:
            raise ValueError(f"Invalid prop_type: {prop_type}")

        red_prop: Prop = prop_class(self.pictograph, red_prop_Dict)
        blue_prop: Prop = prop_class(self.pictograph, blue_prop_Dict)

        red_prop.set_svg_color(RED)
        blue_prop.set_svg_color(BLUE)

        props = {RED: red_prop, BLUE: blue_prop}
        return props

    def init_ghost_arrows(self) -> Dict[Colors, GhostArrow]:
        default_red_ghost_arrow_attributes = {
            COLOR: RED,
            MOTION_TYPE: PRO,
            ROTATION_DIRECTION: CLOCKWISE,
            ARROW_LOCATION: NORTHEAST,
            START_LOCATION: NORTH,
            END_LOCATION: EAST,
            TURNS: 0,
        }

        default_blue_ghost_arrow_attributes = {
            COLOR: BLUE,
            MOTION_TYPE: PRO,
            ROTATION_DIRECTION: CLOCKWISE,
            ARROW_LOCATION: SOUTHWEST,
            START_LOCATION: SOUTH,
            END_LOCATION: WEST,
            TURNS: 0,
        }

        red_ghost_arrow = GhostArrow(
            self.pictograph, default_red_ghost_arrow_attributes
        )
        blue_ghost_arrow = GhostArrow(
            self.pictograph, default_blue_ghost_arrow_attributes
        )

        ghost_arrows = {RED: red_ghost_arrow, BLUE: blue_ghost_arrow}
        return ghost_arrows

    def init_ghost_props(self, prop_type: PropTypes) -> Dict[Colors, GhostProp]:
        prop_class_mapping = {
            STAFF.lower(): Staff,
            BIGSTAFF.lower(): BigStaff,
            CLUB.lower(): Club,
            FAN.lower(): Fan,
            MINIHOOP.lower(): MiniHoop,
            BUUGENG.lower(): Buugeng,
            TRIAD.lower(): Triad,
            BIGTRIAD.lower(): BigTriad,
            BIGHOOP.lower(): BigHoop,
            DOUBLESTAR.lower(): DoubleStar,
            BIGDOUBLESTAR.lower(): BigDoubleStar,
            QUIAD.lower(): Quiad,
            SWORD.lower(): Sword,
            GUITAR.lower(): Guitar,
            UKULELE.lower(): Ukulele,
            CHICKEN.lower(): Chicken,
        }

        prop_class = prop_class_mapping.get(prop_type)
        if prop_class is None:
            raise ValueError(f"Invalid prop_type: {prop_type}")

        default_red_ghost_prop_attributes = {
            COLOR: RED,
            PROP_TYPE: prop_type,
            LOCATION: EAST,
            LAYER: 1,
            ORIENTATION: IN,
        }

        default_blue_ghost_prop_attributes = {
            COLOR: BLUE,
            PROP_TYPE: prop_type,
            LOCATION: WEST,
            LAYER: 1,
            ORIENTATION: IN,
        }

        red_ghost_prop = GhostProp(self.pictograph, default_red_ghost_prop_attributes)
        blue_ghost_prop = GhostProp(self.pictograph, default_blue_ghost_prop_attributes)

        ghost_props = {RED: red_ghost_prop, BLUE: blue_ghost_prop}
        return ghost_props

    def init_letter_item(self) -> LetterItem:
        letter_item = LetterItem(self.pictograph)
        self.pictograph.addItem(letter_item)
        letter_item.position_letter_item(letter_item)
        return letter_item

    def init_locations(self, grid: Grid) -> Dict[Locations, Tuple[int, int, int, int]]:
        grid_center = grid.get_circle_coordinates("center_point").toPoint()

        grid_center_x = grid_center.x()
        grid_center_y = grid_center.y()

        ne_boundary = (
            grid_center_x,
            0,
            self.pictograph.width(),
            grid_center_y,
        )
        se_boundary = (
            grid_center_x,
            grid_center_y,
            self.pictograph.width(),
            self.pictograph.height(),
        )
        sw_boundary = (0, grid_center_y, grid_center_x, self.pictograph.height())
        nw_boundary = (
            0,
            0,
            grid_center_x,
            grid_center_y,
        )
        locations = {
            NORTHEAST: ne_boundary,
            SOUTHEAST: se_boundary,
            SOUTHWEST: sw_boundary,
            NORTHWEST: nw_boundary,
        }
        return locations

    def update_props_and_ghost_props(self, new_prop_type: PropTypes) -> None:
        self.pictograph.props = self.init_props(new_prop_type)
        self.pictograph.prop_type = new_prop_type
        self.pictograph.ghost_props = self.init_ghost_props(new_prop_type)


import logging

from django.contrib.auth.models import User
from django.core.exceptions import ObjectDoesNotExist
from celery import shared_task

from allianceauth.notifications import notify
from allianceauth.services.hooks import NameFormatter
from allianceauth.services.tasks import QueueOnce
from .manager import DiscourseManager
from .models import DiscourseUser

logger = logging.getLogger(__name__)

class DiscourseTasks:
    def __init__(self):
        pass

    @classmethod
    def delete_user(cls, user, notify_user=False):
        if cls.has_account(user) and user.discourse.enabled:
            logger.debug("User %s has a Discourse account. Disabling login." % user)
            if DiscourseManager.disable_user(user):
                user.discourse.delete()
                if notify_user:
                    notify(user, 'Discourse Account Disabled', level='danger')
                return True
        return False

    @staticmethod
    def has_account(user):
        """
        Check if the user has a discourse account
        :param user: django.contrib.auth.models.User
        :return: bool
        """
        try:
            return user.discourse.enabled
        except ObjectDoesNotExist:
            return False

    @staticmethod
    @shared_task(bind=True, name='discourse.update_groups', base=QueueOnce)
    def update_groups(self, pk):
        user = User.objects.get(pk=pk)
        logger.debug("Updating discourse groups for user %s" % user)
        try:
            DiscourseManager.update_groups(user)
        except:
            logger.warn("Discourse group sync failed for %s, retrying in 10 mins" % user)
            raise self.retry(countdown=60 * 10)
        logger.debug("Updated user %s discourse groups." % user)

    @staticmethod
    @shared_task(name='discourse.update_all_groups')
    def update_all_groups():
        logger.debug("Updating ALL discourse groups")
        for discourse_user in DiscourseUser.objects.filter(enabled=True):
            DiscourseTasks.update_groups.delay(discourse_user.user.pk)

    @staticmethod
    def get_username(user):
        from .auth_hooks import DiscourseService
        return NameFormatter(DiscourseService(), user).format_name()


import requests
from bs4 import BeautifulSoup
from fake_useragent import UserAgent

ua = UserAgent()
header = {'user-agent': ua.firefox}

google_page = 'https://www.google.com'
autocomplete = 'https://www.'

def target_url():
    input_url = input("BS4 PARSER."
                      "\n\t(Default display: google.com) "
                      "\n\nINPUT URL:")

    if input_url == "":
        input_url = google_page
    elif autocomplete not in input_url:
        input_url = autocomplete + input_url

    requested_url = requests.get(input_url, headers=header)
    soup = BeautifulSoup(requested_url.content, 'lxml')  # html.parser

    print(soup.prettify())

    with open("scraped.txt", "w", encoding="utf-8") as f:
        f.write(soup.prettify())
        f.close()

if __name__ == '__main__':
    target_url()


import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

img = cv.imread('El.jpg')

blank = np.zeros(img.shape[:2],dtype='uint8')#for same size as image

mask = cv.circle(blank,(img.shape[1]//2,img.shape[0]//2),100,255,-1)
##cv.imshow('Circle',circle)

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

#mask = cv.bitwise_and(gray,gray,mask=circle)
masked = cv.bitwise_and(img,img,mask=mask)# for color histogram
#cv.imshow('Mask',mask)
# grayscale histogram --> distribution of pixels across the image
#gray_hist = cv.calcHist([gray],[0],None,[256],[0,256])
#(images,channels,mask,histSize,ranges,hist=None,accumulate=None)
#gray_hist = cv.calcHist([gray],[0],mask,[256],[0,256])
#plt.figure()
#plt.title('Grayscale Histogram')
#plt.xlabel('Bins')
#plt.ylabel('# of pixels')
#plt.plot(gray_hist)
#plt.xlim([0,256])
#plt.show()

#Color Histogram

plt.figure()
plt.title('Color Histogram')
plt.xlabel('Bins')
plt.ylabel('# of pixels')

colors = ('b','g','r')

for i,col in enumerate(colors):
    hist = cv.calcHist([img],[i],None,[256],[0,256])
    plt.plot(hist,color=col)
    plt.xlim([0,256])
plt.show()

cv.waitKey(0)
cv.destroyAllWindows()


class Solution:
    import itertools
    import sys
    def threeSumClosest(self, nums: 'List[int]', target: 'int') -> 'int':
        min_num = sys.maxsize
        res = 0
        for i in list(map(sum,list(itertools.combinations(nums, 3)))):
            if abs(i - target) < min_num:
                min_num = abs(i - target)
                res = i
        return res


import cv2,threading,time,traceback,sys
import numpy as np
import multiprocessing
from numpy import linalg as LA

class ThreadImage(threading.Thread):
    current_grab = None
    stop = False
    cap = None
    def __init__(self):
        threading.Thread.__init__(self)
        self.cap  = cv2.VideoCapture(1)
        print("Thread setup")
    def run(self):
        print("Thread running")
        while not self.stop:
            ret, frame = self.cap.read()
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            self.current_grab = gray
        print("Thread exiting...")
    def stop_command(self):
        self.stop = True
    def grab_frame(self):
        return self.current_grab
def rotateImage(param):
    image = param[1]
    angle = param[0]
    image_center = tuple(np.array(image.shape[1::-1]) / 2)
    rot_mat = cv2.getRotationMatrix2D(image_center, angle, 1.0)
    result = cv2.warpAffine(image, rot_mat, image.shape[1::-1], flags=cv2.INTER_LINEAR)
    return result
def rotate(pool3,img,degree):
    work = []
    skip = 1
    final_array = []
    for x in range(degree*-1,degree+1,skip):
        work.append([x,img])

    results = pool3.map(rotateImage,work)
    for result in results:
        final_array.append(result)
    return final_array

def array_ripper(param):
    array = param[1]
    output = []
    index = param[0]
    size = param[2]
    rows,cols = array.shape
    row_max = int(rows/size)*size
    col_max = int(cols/size)*size
    row_matrix = []
    time3 = time.time()
    skip = 2
    for y in range(0,col_max,size):
        count = 0
        sum_colors = 0
        for x2 in range(index*size,(index*size)+size,skip):
            for y2 in range(y,y+size,skip):
                try:
                    rgb = array[x2][y2]
                    if rgb > 120:
                        sum_colors += 255
                    else:
                        sum_colors += 0
                    #sum_colors += rgb
                    count += 1
                except:
                    #print("self.array",len(self.array))
                    print(x2)
                    #print("BREAK")
                    #sys.exit(0)
        row_matrix.append(float(sum_colors/count))
    return row_matrix
def get_array3(pool2,img,localization_size):

    col_max = int(len(img[0])/localization_size)*localization_size
    row_max = int(len(img)/localization_size)*localization_size
    #print("col_max",col_max)
    #print("len(img[0])",len(img[0]))
    #print("len(img)",len(img))
    #print("localization_size",localization_size)

    thread_rows = 1

    total_threads = int(len(img)/(thread_rows*localization_size))
    #print(total_threads,"total_threads")

    #final_array = []*total_threads
    final_array = []

    work = []
    for x in range(0,total_threads):
        work.append([x,img,localization_size])

    results = pool.map(array_ripper,work)
    for result in results:
        final_array.append(result)
        #print("Result::",result)
    #print("len(final_array)",len(final_array))
    #print("len(final_array[0])",len(final_array[0]))
    return final_array

def matcher(receive):
    index = receive[0]
    floor_matrix = receive[1]
    grab_matrix = receive[2]
    #print("index :: ",index)
    time1 = time.time()
    exit_cond = False
    min_score = 100000000
    min_score_card = None
    min_start_coordinate = [0,0]
    min_floor = []
    check_count = 0
    skip = 1
    finished = False
    for y in range(0,len(floor_matrix[0])-len(grab_matrix[0])):
        score = []
        floor_match = []
        run = 0
        exit_cond = False
        for xg in range(0,len(grab_matrix),skip):
            floor_match_row = []
            for yg in range(len(grab_matrix[0])-1,-1,-1*skip):
                #print("x+xg",x+xg)
                #print("yg",yg)
                #this could use some tweaking
                if(yg >= 5):
                    distance_factor = 1
                else:
                    distance_factor = 1/(len(grab_matrix[0])-yg)
                try:
                    #check_count += 1
                    floor_match_row.append(floor_matrix[index+xg][y+yg])
                    value = abs(floor_matrix[index+xg][y+yg]-grab_matrix[xg][yg])*distance_factor
                    #print("floor_matrix[index+xg][y+yg]",floor_matrix[index+xg][y+yg])
                    #print("grab_matrix[xg][yg]",grab_matrix[xg][yg])
                    #print("value",value)
                except:
                    traceback.print_exc()

                #print("value",value)
                score.append(value)
            if min_score_card != None:
                if score[run] > min_score_card[run] or sum(score) > min_score:
                    exit_cond = True
                    break
            run += 1
            floor_match.append(floor_match_row)
        if sum(score) < min_score and not exit_cond:
            min_floor = floor_match
            min_score = sum(score)
            min_score_card = score
            min_start_coordinate = [y,index]
    time2 = time.time()
    exc_time = time2-time1
    #print("exc_time",exc_time)

    return [min_floor,min_score,min_score_card,min_start_coordinate]

def find_match3(grab_matrix, floor_matrix, pool):
    #print("FIND MATCH")
    #print("----------")
    scores = []
    #print(len(grab_matrix[0]))
    #print(len(grab_matrix))
    min_score = 255*len(grab_matrix)*len(grab_matrix[0])
    min_score_card = None
    min_start_coordinate = [0,0]
    min_floor = []
    check_count = 0
    skip = 1
    indexes = range(0,len(floor_matrix)-len(grab_matrix))
    #print("Check2")

    #print("Check3")
    #print(indexes)
    send = []
    for x in indexes:
        send.append([x,floor_matrix,grab_matrix])
    results = pool.map(matcher,send)
    #print(results)
    #pool.close()
    #pool.join()
    #print("Check5")
    time2 = time.time()
    fork_time = time2-time1
    #print("fork_time",fork_time)
    for result in results:
        if result[1] < min_score:
            min_floor = result[0]
            min_score = result[1]
            min_score_card = result[2]
            min_start_coordinate = result[3]

    #print("all(fin)",all(fin))

    #print("check_count",check_count)
            #print(score)
            #print(sum(score))
    #print("min score :: ",min_score)
    #print("min coordinate :: ",min_start_coordinate)
    #print("Matrix card ")
    #print("-----------")
    #print(min_score_card)
    #print("Matrix match")
    #print(min_floor)

    return min_score, min_start_coordinate

def outline_region(min_location,matrix_values,floor_img,square_size):
    time1 = time.time()
    x1 = min_location[0]*square_size
    y1 = min_location[1]*square_size
    print("X1:",x1,"Y1:",y1)
    #print("x1",x1)
    #print("y1",y1)
    x2 = x1+len(matrix_values[0])*square_size+square_size
    y2 = y1+len(matrix_values)*square_size+square_size
    #print("x2",x2)
    #print("y2",y2)

    cv2.line(floor_img,(x1,y1),(x1,y2),(0,255,0),5)
    cv2.line(floor_img,(x1,y1),(x2,y1),(0,255,0),5)
    cv2.line(floor_img,(x1,y2),(x2,y2),(0,255,0),5)
    cv2.line(floor_img,(x2,y1),(x2,y2),(0,255,0),5)

    #cv2.imshow('Detection zone', floor_img)
    #cv2.imwrite('detect.png',floor_img)
    time2 = time.time()
    exc_time = time2-time1
    #print("Exc time",exc_time)
    return floor_img

class ThreadCopy(threading.Thread):
    import numpy as np
    image = None
    output = None
    copy_image = True
    def __init__(self,image):
        threading.Thread.__init__(self)
        self.image = image
        self.output = np.copy(self.image)
    def run(self):
        while True:
            if self.copy_image:
                self.output = np.copy(self.image)
                self.copy_image = False
            time.sleep(0.001)
    def get_copy(self):
        return self.output
    def request_copy(self):
        self.copy_image = True

if __name__ == "__main__":
    pool = multiprocessing.Pool(6)
    pool2 = multiprocessing.Pool(4)
    pool3 = multiprocessing.Pool(2)
    grab_matrix = None
    floor = cv2.imread("floor30.png",cv2.IMREAD_GRAYSCALE)
    floor_rgb = cv2.cvtColor(floor,cv2.COLOR_GRAY2RGB)
    imS = cv2.resize(floor_rgb, (180,360))
    #imS = floor_rgb
    tcopy = ThreadCopy(imS)
    tcopy.start()
    ti = ThreadImage()
    ti.start()
    check = False
    rows = 0
    cols = 0
    size_grab = 50
    mismatch = 30
    floor_matrix = get_array3(pool2,floor,mismatch)
    print("Floor matrix loaded")
    avg = 1
    run_cnt = 0
    avg_time = 0
    max_score = 0
    while True:

        try:
            time1 = time.time()
            tcopy.request_copy()

            grab = ti.grab_frame()

            if not check:
                rows,cols = grab.shape
                for x in range(rows):
                    for y in range(cols):
                        if(y >= 5):
                            max_score += 255
                        else:
                            max_score = 255*(1/(cols-y))
                print("max_score",max_score)

                check = True

            time2 = time.time()
            time_grab = time2-time1
            pts1 = np.float32([[182,25],[442,25],[1,358],[638,366]])
            pts2 = np.float32([[0,0],[200,0],[0,400],[200,400]])

            M = cv2.getPerspectiveTransform(pts1,pts2)

            corrected = cv2.warpPerspective(grab,M,(200,400))

            for x in range(0,cols,size_grab):
                for y in range(0,rows,size_grab):
                    cv2.rectangle(corrected,(x,y),(x+size_grab,y+size_grab),5)

            rotated_image = rotate(pool3,corrected,4)

            time3 = time.time()
            test_matricies = []
            for x in range(len(rotated_image)):
                test_matricies.append(get_array3(pool2,rotated_image[x],size_grab))
            time4 = time.time()
            time_get_array = time4-time3

            time5 = time.time()
            #floor_with_match = floor_rgb.copy()
            mins = []
            for x in range(len(test_matricies)):
                min_score, min_start_coordinate = find_match3(test_matricies[x],floor_matrix,pool)
                mins.append([min_score, min_start_coordinate])
            min_score = 255*rows*cols
            min_start_coordinate = None
            min_x = 0
            for x in range(0,len(mins)):
                if mins[x][0] < min_score:
                    min_score = mins[x][0]
                    min_start_coordinate = mins[x][1]
                    min_x = x
            time6 = time.time()
            time_find_match = time6 - time5
            font = cv2.FONT_HERSHEY_SIMPLEX
            final_matrix = test_matricies[min_x]
            average_array_display = np.zeros([size_grab*(len(final_matrix)),size_grab*(len(final_matrix[0])),1],np.uint8)
            for y in range(len(final_matrix[0])):
                for x in range(len(final_matrix)):
                    #print("final_matrix[x][y]",final_matrix[x][y])
                    color = int(final_matrix[x][y])
                    cv2.rectangle(average_array_display,(y*size_grab,x*size_grab),(y*size_grab+size_grab,x*size_grab+size_grab),(color),-1)
                    cv2.putText(average_array_display,str(color),(int(y*size_grab+size_grab/2),int(x*size_grab+size_grab/2 - 10)), font, 0.4,(0,0,0),1,cv2.LINE_AA)
                    cv2.putText(average_array_display,str(color),(int(y*size_grab+size_grab/2),int(x*size_grab+size_grab/2 + 10)), font, 0.4,(255,255,255),1,cv2.LINE_AA)

            #if min_score < 2200:
            time7 = time.time()
            floor_with_match = outline_region(min_start_coordinate,test_matricies[min_x],tcopy.get_copy(),15)

            percent_match = 100*((max_score-min_score)/max_score)
            cv2.rectangle(floor_with_match,(0,0),(188,20),(255,255,255),-1)
            text = str(min_score)
            #text2 = "%"+str(percent_match)
            cv2.putText(floor_with_match,text,(12,12), font, 0.4,(0,0,0),1,cv2.LINE_AA)
            #cv2.putText(floor_with_match,text2,(12,24), font, 0.4,(0,0,0),1,cv2.LINE_AA)

            cv2.imshow("area",floor_with_match)
            cv2.imshow("matrix",rotated_image[min_x])
            cv2.imshow("average",average_array_display)
            cv2.imshow("perspective",corrected)

            time8 = time.time()
            time_else = time8 - time7

            if(run_cnt%avg == 0 and run_cnt != 0):

                #print("time_grab",time_grab)
                #print("time_get_array",time_get_array)
                #print("time_find_match",time_find_match)
                #print("time_else",time_else)
                #print("total time",str(time8-time1))
                avgeraged_time = float(avg_time/avg)
                if avg == 1:
                    avgeraged_time = time8-time1
                #print("avgeraged_time",avgeraged_time)
                frequ = float(1/avgeraged_time)
                print("Frequency",frequ)
                avg_time = 0
            else:
                avg_time += time8-time1

            run_cnt += 1

            #sys.exit(1)
            if cv2.waitKey(1) & 0xFF == ord('q'):
                cv2.imwrite('grab_test.png',grab)
                break

        except:
            traceback.print_exc()


import atexit
import logging
import queue
import threading
import weakref
from concurrent.futures import Executor, Future
from dataclasses import dataclass
from threading import Thread
from typing import Callable, Union, Type, List

logger = logging.getLogger(__name__)

@dataclass
class PoolState:
    # Special class to hold all Poll data. It is safe to have strong reference on it
    max_thread_idle_time: float
    name: str

    queue: "queue.Queue[Union[Type[DieTask], TaskItem]]"
    resurrector_event: threading.Event
    shutting_down: bool = False
    die_task_reached: bool = False

@dataclass
class TaskItem:
    future: Future
    func: Callable
    args: tuple
    kwargs: dict

    def run(self):
        try:
            result = self.func(*self.args, **self.kwargs)
        except BaseException as exc:
            self.future.set_exception(exc)
            # Break a reference cycle with the exception 'exc'
            self = None
        else:
            self.future.set_result(result)

class DieTask:
    # Used to notify Worker that it should exit
    pass

class _WorkerThread(Thread):

    def __init__(self, name: str, pool_state: PoolState):
        super().__init__(name=name, daemon=True)
        self.pool_state = pool_state

    class StopException(Exception):
        pass

    def main_loop(self):
        try:
            task = self.pool_state.queue.get(timeout=self.pool_state.max_thread_idle_time)
        except queue.Empty:
            raise self.StopException()  # We were idle for `max_thread_idle_time`, so we should exit now
        else:
            if task is DieTask:
                self.pool_state.queue.put(task)
                self.pool_state.die_task_reached = True
                raise self.StopException()
            elif task.future.set_running_or_notify_cancel():
                task.run()

    def run(self) -> None:
        logger.info(f'WorkerThread {self.name} starting')
        try:
            while True:
                self.main_loop()
        except self.StopException:
            logger.info(f'WorkerThread {self.name} shutting down')

class _ResurrectorThread(Thread):
    base_timeout = 0.01
    max_timeout = 2

    _worker_threads_id: int
    threads: List[_WorkerThread]

    def __init__(self, name: str, pool_state: PoolState):
        super().__init__(name=name, daemon=True)
        self._worker_threads_id = 1
        self.threads = []
        self.pool_state = pool_state

    def run(self) -> None:
        logger.info(f'ResurrectorThread {self.name} starting')
        timeout = self.base_timeout
        while not self.pool_state.die_task_reached:
            if not self.pool_state.queue.empty():
                # This means that there are more tasks then workers
                worker_thread = _WorkerThread(
                    name=f'{self.pool_state.name}WorkerThread {self._worker_threads_id}',
                    pool_state=self.pool_state,
                )
                self.threads.append(worker_thread)
                worker_thread.start()
                self._worker_threads_id += 1
                timeout = self.base_timeout
            else:
                timeout = min(timeout * 2, self.max_timeout)

            if self.pool_state.resurrector_event.wait(timeout=timeout):
                self.pool_state.resurrector_event.clear()

        for thread in self.threads:
            thread.join()
        logger.info(f'ResurrectorThread {self.name} shutting down')

def _atexit_handler(executor_ref):
    executor = executor_ref()
    if executor and not executor.state.shutting_down:
        executor.shutdown(wait=True)

class UnboundedThreadPoolExecutor(Executor):
    state: PoolState
    _resurrector_thread: _ResurrectorThread
    _shutdown_lock: threading.Lock

    def __init__(self, name: str = 'UnboundedThreadPoolExecutor', max_thread_idle_time: float = 30):
        self.state = PoolState(
            name=name,
            max_thread_idle_time=max_thread_idle_time,
            queue=queue.Queue(),
            resurrector_event=threading.Event(),
        )
        self._resurrector_thread = _ResurrectorThread(
            name=f'{name}ResurrectorThread',
            pool_state=self.state,
        )
        self._resurrector_thread.start()
        self._shutdown_lock = threading.Lock()

        atexit.register(_atexit_handler, weakref.ref(self))

    def submit(*args, **kwargs):
        # Copy-pasted from concurrent.futures.thread.ThreadPoolExecutor
        # this is required to support passing fn both as args and kwarg
        if len(args) >= 2:
            self, fn, *args = args
        elif not args:
            raise TypeError("descriptor 'submit' of 'ThreadPoolExecutor' object "
                            "needs an argument")
        elif 'fn' in kwargs:
            fn = kwargs.pop('fn')
            self, *args = args
            import warnings
            warnings.warn("Passing 'fn' as keyword argument is deprecated",
                          DeprecationWarning, stacklevel=2)
        else:
            raise TypeError('submit expected at least 1 positional argument, '
                            'got %d' % (len(args) - 1))
        with self._shutdown_lock:
            if self.state.shutting_down:
                raise RuntimeError('cannot schedule new futures after shutdown')
            future = Future()
            self.state.queue.put(TaskItem(future, fn, args, kwargs))
            self.state.resurrector_event.set()
            return future

    def __del__(self):
        # If there is no reference, there can be no race with .submit call
        self.state.shutting_down = True
        self.state.queue.put(DieTask)
        self.state.resurrector_event.set()

    def shutdown(self, wait=True):
        with self._shutdown_lock:
            self.state.shutting_down = True
            self.state.queue.put(DieTask)
            self.state.resurrector_event.set()

        if wait:
            self._resurrector_thread.join()


import PIL
from PIL import Image, ImageDraw, ImageColor, ImageTk

class Render:

    @staticmethod
    def draw_grid(color: str = None):
        if color is None:
            color = 'green'

        img = Image.new(mode="RGB", size=(612, 612), color='black')

        image = ImageDraw.Draw(img)

        for i in range(1, 5):
            x, y = 123 * i, 123 * i
            image.line((x-2, 0, x-2, 612), width=3, fill=ImageColor.getrgb(color))
            image.line((0, y-2, 612, y-2), width=3, fill=ImageColor.getrgb(color))

        return img

    @staticmethod
    def render_unit(img, x: int, y: int):
        img.paste(Image.open("./assets/test.png"), (x,y))
        return img


#!/usr/bin/python3.7
from itertools import repeat
from string import ascii_uppercase
from json import dumps

def analyse_freq(text):
    freq = dict(zip(ascii_uppercase, repeat(0)))
    most_common = ['E', 'T', 'A', 'O', 'I', 'N', 'S', 'R', 'H', 'D', 'L', 'U', 'C', 'M', 'F', 'W', 'G', 'Y', 'P', 'B', 'V', 'K', 'X', 'J', 'Q', 'Z']
    for i in text:
        freq[i]+=1
    s = sorted(freq, key=(lambda x: freq[x]), reverse=True)
    return dict(zip(s, most_common))

texts = [open("spam/{}".format(i)).read() for i in range(7)]

for i, mapping in enumerate(map(analyse_freq, texts)):
    open("mappings/{}".format(i), "w").write(dumps(mapping))


import re
from telegram import ForceReply, Update
from telegram.ext import Application, CommandHandler, ContextTypes, MessageHandler, filters
import logging
MY_TOKEN = "YOUR TOKEN"

logging.basicConfig(
    format="%(asctime)s - %(name)s - %(levelname)s - %(message)s", level=logging.INFO
)
logger = logging.getLogger(__name__)

def clearExpresiion(input_str: str):
    return re.sub(r'[^\d+=*%^/\(\)\-]', "", input_str)

def calc(expresiion: str):
    cleared_expresion = clearExpresiion(expresiion)
    return eval(cleared_expresion)

async def start(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    """Send a message when the command /start is issued."""
    logger.info("Start")
    await update.message.reply_text(
        "Добро пожаловать в калькулятор, введите выражение для расчета, например: 1 + 2"
    )

async def echo(update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
    logger.info("User input {}".format(update.message.text))
    result = calc(update.message.text)
    logger.info("Result is: {}".format(update.message.text))
    message = f"Результат выражения: {result}"
    await update.message.reply_text(message)

def main() -> None:
    """Start the bot."""
    logger.info("Bot started!")
    # Create the Application and pass it your bot's token.
    application = Application.builder().token(MY_TOKEN).build()

    # on different commands - answer in Telegram
    application.add_handler(CommandHandler("start", start))

    # on non command i.e message - echo the message on Telegram
    application.add_handler(MessageHandler(
        filters.TEXT & ~filters.COMMAND, echo))

    # Run the bot until the user presses Ctrl-C
    application.run_polling()

if __name__ == "__main__":
    main()


from django.db import models
from django.contrib.postgres.fields import ArrayField

import datetime
from django.dispatch import receiver
from django.db.models import Q

import re

class Location(models.Model):
    # loc is my own classification of location
    loc = models.CharField(max_length=20)
    warehouse_location = models.CharField(max_length=10, default="USLA")
    area = models.CharField(max_length=2)
    aisle_letter = models.CharField(max_length=3, default="")
    aisle_num = models.IntegerField()
    level = models.IntegerField()
    column = models.IntegerField()

    def __str__(self):
        loc_name = self.warehouse_location + "." + self.area + "." +\
                   self.aisle_letter + str(self.aisle_num) + "." + \
                   str(self.column) + "." + str(self.level)
        return loc_name

def make_location(warehouse_location, area, aisle_letter, aisle_num, column, level):
    location_inst = Location(warehouse_location=warehouse_location,
                             area=area,
                             aisle_letter=aisle_letter,
                             aisle_num=aisle_num,
                             column=column,
                             level=level,
                             )
    loc = ''
    if area == "PH" or area == "PA":
        loc = "P"
    elif area == "S":
        if aisle_num == 60:
            loc = "VC"
        else:
            loc = "S"
    elif area == "F":
        loc = "F"
    elif area == "VA" or area == "VB":
        if aisle_num == 44:
            loc = "VC"
        else:
            loc = "F"
    elif area == "VC" or area == "VD":
        loc = "VC"
    elif area == "H":
        if aisle_letter == "H":
            loc = "S"
        elif aisle_num == 8:
            loc = "S"
        elif aisle_num <= 6:
            loc = "VC"
    location_inst.loc = loc

    location_inst.save()
    return location_inst

def filter_item_query_by_loc(item_query, loc):
    if loc == "P":
        return item_query.filter( Q(rack_location__area="PH") | Q(rack_location__area="PA"))
    elif loc == "VC":
        q1 = Q(rack_location__area="VC")
        q2 = Q(rack_location__area="VD")
        q3 = (Q(rack_location__aisle_num=44) & Q(rack_location__area="VA"))
        q4 = (Q(rack_location__aisle_num=44) & Q(rack_location__area="VB"))
        q5 = (Q(rack_location__aisle_num=60) & Q(rack_location__area="S"))
        q6 = (Q(rack_location__area="H") & Q(rack_location__aisle_num__lte=6) & ~Q(rack_location__aisle_letter="H") )
        return item_query.filter(q1 | q2 | q3 | q4 | q5 | q6)
    elif loc == "S":
        q1 = (~Q(rack_location__aisle_num=60) & Q(rack_location__area="S"))
        q2 = (Q(rack_location__area="H" ) & Q(rack_location__aisle_letter="H"))
        q3 = (Q(rack_location__area="H") & Q(rack_location__aisle_num=8))
        return item_query.filter(q1 | q2 | q3)
    elif loc == "F":
        q1 = Q(rack_location__area="F")
        q2 = (~Q(rack_location__aisle_num=44) & Q(rack_location__area="VA"))
        q3 = (~Q(rack_location__aisle_num=44) & Q(rack_location__area="VB"))
        return item_query.filter(q1 | q2 | q3)
    return item_query

class DataDate(models.Model):
    date = models.DateTimeField()

class Items(models.Model):
    item_id = models.IntegerField()
    lab_id = models.IntegerField(default = 0)
    item_weight = models.FloatField(default = 0)
    avail_quantity = models.IntegerField()
    ship_quantity = models.IntegerField()
    location_code = models.CharField(max_length=20, default="")
    fifo_date = models.DateTimeField()
    iv_create_date = models.DateTimeField(default=datetime.datetime.now)
    rack_location = models.ForeignKey(Location, on_delete=models.CASCADE, default=None)
    rcv = models.CharField(max_length=20)
    data_date = models.ForeignKey(DataDate, on_delete=models.CASCADE, default=None)
    description = models.CharField(max_length=100, default="")
    item_code = models.CharField(max_length=50, default="")
    customer_code = models.IntegerField(default="0")
    last_out_date = models.DateTimeField(blank=True, null=True, default=None)

    def get_input_date(self):
        rcv = self.rcv
        recv_re = re.compile("^RECV")
        if recv_re.match(rcv):
            return self.iv_create_date
        else:
            return self.fifo_date


import cv2
import numpy as np

image = cv2.imread('sample.jpg', 0)
cv2.imshow("Original", image)

ret, thresh1 = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)
cv2.imshow('Binary Threshold', thresh1)

ret, thresh2 = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY_INV)
cv2.imshow('Threshold Binary Inverse', thresh2)

ret, thresh3 = cv2.threshold(image, 127, 255, cv2.THRESH_TRUNC)
cv2.imshow('Thresh Trunc', thresh3)

ret, thresh4 = cv2.threshold(image, 127, 255, cv2.THRESH_TOZERO)
cv2.imshow('Threshold zero', thresh4)

ret, thresh5 = cv2.threshold(image, 127, 255, cv2.THRESH_TOZERO_INV)
cv2.imshow('Threshold zero inv', thresh5)
cv2.waitKey()
cv2.destroyAllWindows()

blur_img = cv2.GaussianBlur(image, (3, 3), 0)

#adaptive threshsold
adaptive_threshold = cv2.adaptiveThreshold(image, 255, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 3, 5)
cv2.imshow("Adaptive Mean Thresholding", adaptive_threshold)
cv2.waitKey()

#Otsu's Thresholding
_, otsus_threshold = cv2.threshold(image, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)
cv2.imshow("Otsu's Threshold", otsus_threshold)
cv2.waitKey()

cv2.destroyAllWindows()


from flask import Flask
import random

app = Flask(__name__)
rand_num = random.randint(0, 9)

@app.route("/")
def hello_world(text="Guess a number between 0 & 9",
                image="https://media.giphy.com/media/3o7aCSPqXE5C6T8tBC/giphy.gif"):
    return f'
{text}
' \
           f''

@app.route("/<int:number>")
def guess(number):
    if number > rand_num:
        return hello_world(text="Too high, try again!", image="https://media.giphy.com/media/3o6ZtaO9BZHcOjmErm/giphy.gif")
    elif number < rand_num:
        return hello_world(text="Too low, try again!", image="https://media.giphy.com/media/jD4DwBtqPXRXa/giphy.gif")
    else:
        return hello_world(text="You found me!", image="https://media.giphy.com/media/4T7e4DmcrP9du/giphy.gif")

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


import cv2
import numpy as np
import matplotlib.pyplot as plt

# Function to convert image to grayscale, apply gaussian blur and detect edges
def canny(image):
    gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY)
    # To reduce image noise use Gaussian blur (from sharp image get smooth image)
    # cv2.GaussianBlur(input image, kernel matrix, standard deviation)
    blur = cv2.GaussianBlur(gray, (5, 5), 0)
    # Canny edge detection -> search for high value (color) difference between neighbour pixels i.e. edges
    # cv2.Canny (input image, first treshold, second treshhold)
    canny = cv2.Canny(blur, 50, 150)
    return canny

def display_lines(image, lines):
    line_image = np.zeros_like(image) # Black image
    if lines is not None:
        for x1, y1, x2, y2 in lines:
            # Draw lines
            # cv2.line(input image, start point, end point, color, thickness)
            cv2.line(line_image, (x1, y1), (x2, y2), (255,0,0), 10)
    return line_image

# Function to create white triangle and black mask of the input image.
# Apply AND bitwise operation on those 2 to get area of interest (lanes)
def region_of_interest(image):
    height = image.shape[0]
    # Define triangle with its verticies
    polygons = np.array([
    [(200, height), (1100, height), (550, 250)]
    ])
    # Return an array of zeros with the same shape and type as a given array(image)
    # i.e. make black image with the same size of input image
    mask = np.zeros_like(image)
    # On black mask apply white(255) triangle
    cv2.fillPoly(mask, polygons, 255)
    # Isolate area of interest and fill rest with zeros (black)
    # Preform AND operation on elements from 2 arrays (image, mask)
    masked_image = cv2.bitwise_and(image, mask)
    return masked_image

def make_coordinates(image, line_parameters):
    slope, intercept = line_parameters
    y1 = image.shape[0]
    y2 = int(y1*(3/5))
    x1 = int((y1 - intercept) / slope)
    x2 = int((y2 - intercept) / slope)
    return np.array([x1, y1, x2, y2])

def average_slope_intercept(image, lines):
    left_fit = []
    right_fit = []
    for line in lines:
        x1, y1, x2, y2 = line.reshape(4)
        parameters = np.polyfit((x1, x2), (y1, y2), 1)
        slope = parameters[0]
        intercept = parameters[1]
        if slope < 0:
            left_fit.append((slope, intercept))
        else:
            right_fit.append((slope, intercept))
    left_fit_average = np.average(left_fit, axis=0)
    right_fit_average = np.average(right_fit, axis=0)
    left_line = make_coordinates(image, left_fit_average)
    right_line = make_coordinates(image, right_fit_average)
    return np.array([left_line, right_line])

# Load image, make copy of it
image = cv2.imread('test_image.jpg')
lane_image = np.copy(image)
"""
canny_image = canny(lane_image)
cropped_image = region_of_interest(canny_image)
# https://bit.ly/2XQgX7I
# cv2.HoughLinesP(input image, rho, theta, treshold, placeholder array, min length of line, max allowed gap btw lines)
lines = cv2.HoughLinesP(cropped_image, 2, np.pi/180, 100, np.array([]), minLineLength=40, maxLineGap=5)

averaged_lines = average_slope_intercept(lane_image, lines)

line_image = display_lines(lane_image, averaged_lines)

# Blend image to another with defined weights(transparency, translucency)
# https://bit.ly/3iy2gxN
# cv2.addWeighted(original image, alpha, second image, beta, gamma)
combo_image = cv2.addWeighted(lane_image, 0.7, line_image, 1, 1)

# Display result image
cv2.imshow("Image Result", combo_image)
cv2.waitKey(0)
"""
cap = cv2.VideoCapture("test2.mp4")
while(cap.isOpened()):
    _, frame = cap.read()
    canny_image = canny(frame)
    cropped_image = region_of_interest(canny_image)
    lines = cv2.HoughLinesP(cropped_image, 2, np.pi/180, 100, np.array([]), minLineLength=40, maxLineGap=5)
    averaged_lines = average_slope_intercept(frame, lines)
    line_image = display_lines(frame, averaged_lines)
    combo_image = cv2.addWeighted(frame, 0.7, line_image, 1, 1)
    cv2.imshow("Video Result", combo_image)
    if cv2.waitKey(1) == ord('q'):
        break
cap.release()
cv2.destroyAllWindows()


import unittest
import os.path
import os
from datetime import datetime
from models.engine.file_storage import FileStorage
from models import *
from console import HBNBCommand

@unittest.skipIf(os.getenv('HBNB_TYPE_STORAGE', '') == "db", "db")
class Test_FileStorage(unittest.TestCase):
    """
    Test the file storage class
    """

    def setUp(self):
        self.cli = HBNBCommand()
        self.store = FileStorage()

        test_args = {'updated_at': datetime(2017, 2, 12, 00, 31, 53, 331997),
                     'id': 'f519fb40-1f5c-458b-945c-2ee8eaaf4900',
                     'created_at': datetime(2017, 2, 12, 00, 31, 53, 331900)}
        self.model = BaseModel(test_args)

        self.test_len = 0
        if os.path.isfile("file.json"):
            self.test_len = len(self.store.all())

    def test_all(self):
        self.assertEqual(len(self.store.all()), self.test_len)

    def test_new(self):
        self.assertEqual(len(self.store.all()), self.test_len)
        self.model.save()
        self.assertEqual(len(self.store.all()), self.test_len + 1)
        a = BaseModel()
        a.save()
        self.assertEqual(len(self.store.all()), self.test_len + 2)
        self.cli.do_destroy("BaseModel f519fb40-1f5c-458b-945c-2ee8eaaf4900")
        self.cli.do_destroy("BaseModel " + a.id)

    def test_save(self):
        self.test_len = len(self.store.all())
        a = BaseModel()
        a.save()
        self.assertEqual(len(self.store.all()), self.test_len + 1)
        b = User()
        self.assertNotEqual(len(self.store.all()), self.test_len + 2)
        b.save()
        self.assertEqual(len(self.store.all()), self.test_len + 2)
        self.cli.do_destroy("BaseModel " + a.id)
        self.cli.do_destroy("User " + b.id)

    def test_reload(self):
        pass

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


"""
AIML Bot implements an interpreter for AIML, the Artificial Intelligence
Markup Language developed by Dr. Richard Wallace of the A.L.I.C.E. Foundation.
It can be used to implement a conversational AI program.
"""

from setuptools import setup
import glob
import os
import warnings

package_prefix = "Lib/site-packages/aiml_bot"

def get_long_description():
    """Load the long description from the README file. In the process,
    convert the README from .md to .rst using Pandoc, if possible."""
    rst_path = os.path.join(os.path.dirname(__file__), 'README.rst')
    md_path = os.path.join(os.path.dirname(__file__), 'README.md')

    try:
        # Imported here to avoid creating a dependency in the setup.py
        # if the .rst file already exists.

        # noinspection PyUnresolvedReferences,PyPackageRequirements
        from pypandoc import convert_file
    except ImportError:
        warnings.warn("Module pypandoc not installed. Unable to generate README.rst.")
    else:
        # First, try to use convert_file, assuming Pandoc is already installed.
        # If that fails, try to download & install it, and then try to convert
        # again.
        # noinspection PyBroadException
        try:
            # pandoc, you rock...
            rst_content = convert_file(md_path, 'rst')
            with open(rst_path, 'w') as rst_file:
                for line in rst_content.splitlines(keepends=False):
                    rst_file.write(line + '\n')
        except Exception:
            try:
                # noinspection PyUnresolvedReferences,PyPackageRequirements
                from pypandoc.pandoc_download import download_pandoc

                download_pandoc()
            except FileNotFoundError:
                warnings.warn("Unable to download & install pandoc. Unable to generate README.rst.")
            else:
                # pandoc, you rock...
                rst_content = convert_file(md_path, 'rst')
                with open(rst_path, 'w') as rst_file:
                    for line in rst_content.splitlines(keepends=False):
                        rst_file.write(line + '\n')

    if os.path.isfile(rst_path):
        with open(rst_path) as rst_file:
            return rst_file.read()
    else:
        # It will be messy, but it's better than nothing...
        with open(md_path) as md_file:
            return md_file.read()

setup(
    name="AIML Bot",
    version="0.0.3",
    author="Cort Stratton",
    author_email="cort@cortstratton.org",
    license="BSD-2-Clause",
    maintainer="Aaron Hosford",
    maintainer_email="hosford42@gmail.com",
    description="An interpreter package for AIML, the Artificial Intelligence Markup Language",
    long_description=get_long_description(),
    url="https://github.com/hosford42/aiml_bot",

    platforms=["any"],
    classifiers=[
        "Development Status :: 3 - Alpha",
        "Environment :: Console",
        "Intended Audience :: Developers",
        "Programming Language :: Python :: 3",
        "Operating System :: OS Independent",
        "Topic :: Communications :: Chat",
        "Topic :: Scientific/Engineering :: Artificial Intelligence"
    ],

    packages=["aiml_bot"],
    package_data={
        "aiml_bot": ["*.aiml"],
    },
    data_files=[
        ("doc/aiml_bot", glob.glob("*.txt")),
        ("doc/aiml_bot", glob.glob("*.md")),
    ]
)


#!/usr/bin/python3

from personal_data import user_id
from datetime import datetime
import requests
import json
import _phue
import logging
from numpy import mean
import scene
import data
from time import sleep
import toolbox
import sys

log_file = '/home/pi/ambient.log'
MASTER = 31

def trim_logs():
    with open(log_file, "r") as file:
        lines = file.readlines()

    max_number_of_lines = 1 * 24 * 60

    if len(lines) > max_number_of_lines:
        with open(log_file, "w") as file:
            file.writelines(lines[-max_number_of_lines:])

def __get_new(i=MASTER):
    response = requests.get("http://%s/api/%s/sensors/%d" % (
                            _phue.ip_address, user_id, i))
    json_data = json.loads(response.text)
    return json_data["state"]["lightlevel"]

def __get_history(i=MASTER, number=10):
    with open(log_file, "r") as file:
        lines = file.readlines()
    if len(lines) == 0:
        sleep(.1)
        with open(log_file, "r") as file:
            lines = file.readlines()

    if number != float('inf'):
        lines = lines[-number:]
    lines_copy = lines
    try:
        lines = [l.replace("\n", "") for l in lines]
        lines = [l[26:] for l in lines]
        lines = [l.split(";") for l in lines]
        lines = [[jj.replace(" ", "") for jj in j if jj] for j in lines]
        lines = [[jj for jj in j if jj] for j in lines]
        data = dict()
        for l in lines:
            for element in l:
                key, value = element.split(':')
                key = int(key)
                value = float(value)
                if key not in data:
                    data[key] = list()
                data[key].append(value)
        return data[i]
    except:
        print(lines_copy)
        raise

def get_history_mean(i=MASTER, number=10):
    return mean(__get_history(i, number))

def get_simulated_bri():
    g = __get_new()
    bri = toolbox.map(g, 1000, 36000, 0, 1)
    bri = min(bri, 1)
    bri = max(bri, 0)
    return bri

def get_simulated_ct(maximum=1.0, minimum=.35):
    mean = get_history_mean(number=60)
    ct = toolbox.map(mean, 0, 33000, maximum, minimum)
    ct = min(ct, maximum)
    ct = max(ct, minimum)
    return ct

def get_schmitt_trigger(low=16000, high=20000):
    history = __get_history(number=float('inf'))
    for j in history[::-1]:
        if j <= low:
            return False
        elif high <= j:
            return True

def log_all():
    message = ""
    for i in [11, 31, 34, 82]:
        lightlevel = __get_new(i)

        message += str(i)
        message += ": "
        message += str(lightlevel)
        message += "; "

    logging.basicConfig(filename=log_file,
                        encoding='utf-8',
                        level=logging.INFO,
                        format='%(asctime)s   %(message)s')

    logging.info(message)
    trim_logs()

def __minutes_in_current_day():
    now = datetime.now()
    midnight = now.replace(hour=0, minute=0, second=0, microsecond=0)
    minutes_passed = (now - midnight).total_seconds() // 60
    return int(minutes_passed)

limit_ambient = 28000.0
limit_minutes = int(2 * 60)
def should_turn_off():
    return False
    window_minutes = __minutes_in_current_day()
    if window_minutes < limit_minutes:
        return False
    history = __get_history(number=window_minutes)
    history_before = history[:-1]
    nof_elements = len([h for h in history if limit_ambient <= h])
    nof_elements_before = len([h for h in history_before if limit_ambient <= h])
    return (nof_elements == limit_minutes and
            nof_elements_before == limit_minutes - 1)

def should_be_off():
    return False
    window_minutes = __minutes_in_current_day()
    if window_minutes < limit_minutes:
        return False
    history = __get_history(number=window_minutes)
    nof_elements = len([h for h in history if limit_ambient <= h])
    return limit_minutes <= nof_elements

def turn_off_if_ambient_above_limit():
    if should_turn_off():
        scene.transition('off_wohnzimmer', time=10*60)

def auto_ct_enabled():
    try:
        with open('/home/pi/auto_ct_enabled', 'r') as file:
            content = file.read().strip()
        return content.lower() == "true"
    except:
        return False

def enable_auto_ct():
    with open('/home/pi/auto_ct_enabled', 'w') as f:
        f.write('true')

def disable_auto_ct():
    with open('/home/pi/auto_ct_enabled', 'w') as f:
        f.write('false')

def auto_ct():
    if auto_ct_enabled():
        ct_value = get_simulated_ct(maximum=1.0, minimum=0.0)
        for z in ["schlafzimmer", "wohnzimmer"]:
            do_this_room = True
            for light, light_data in eval("data." + z + "_lights"):
                if "bri" in light_data:
                    threshold = data.warm[light]["bri"] - 0.02
                    if _phue.get_bri(light) < threshold:
                        do_this_room = False
            if do_this_room:
                s = toolbox.scene_superposition(ct_value,
                                                eval("data.warm_" + z),
                                                1.0 - ct_value,
                                                eval("data.hell_" + z))
                scene.transition_dicionary(s, time=59)

def main():
    log_all()
    turn_off_if_ambient_above_limit()
    auto_ct()
    trim_logs()

if __name__ == "__main__":
    if len(sys.argv) == 1:
        main()
    else:
        for a in sys.argv[1:]:
            f = globals()[a.strip("-").replace("-", "_")]
            f()


import secrets

from rest_framework import serializers
from rest_framework.validators import UniqueTogetherValidator

from .models import *

class BuildingSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField()

    class Meta:
        model = Building
        fields = [
            'id',
            'owner',
            'building_name',
            'street',
            'area',
            'city',
            'state',
            'zip_code',
            'landmark',
            'latitude',
            'longitude',
            'gender_label',
            'display_pic',
            'in_time'
        ]

    def create(self, validated_data):
        display_pic = None
        if validated_data['display_pic']:
            display_pic = validated_data['display_pic']
            ext = display_pic.name.split('.')[-1]
            display_pic.name = secrets.token_urlsafe(30) + '.' + ext

        building = Building.objects.create(
            owner=validated_data['owner'],
            building_name=validated_data.get('building_name'),
            street=validated_data.get('street'),
            area=validated_data.get('area'),
            city=validated_data.get('city'),
            state=validated_data.get('state'),
            zip_code=validated_data.get('zip_code'),
            landmark=validated_data.get('landmark'),
            latitude=validated_data.get('latitude'),
            longitude=validated_data.get('longitude'),
            gender_label=validated_data.get('gender_label'),
            display_pic=display_pic,
            in_time=validated_data.get('in_time')
        )
        return building

    def update(self, instance, validated_data):
        if validated_data.get('display_pic') != instance.display_pic:
            display_pic = validated_data.get('display_pic')
            ext = display_pic.name.split('.')[-1]
            display_pic.name = secrets.token_urlsafe(30) + '.' + ext
            validated_data['display_pic'] = display_pic
            instance.display_pic = validated_data.get('display_pic', instance.display_pic)

        instance.gender_label = validated_data.get('gender_label', instance.gender_label)
        instance.landmark = validated_data.get('landmark', instance.landmark)
        instance.in_time = validated_data.get('in_time', instance.in_time)
        instance.save()
        return instance

class RoomSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField()

    class Meta:
        model = Room
        fields = [
            'id',
            'building',
            'description',
            'title',
            'rent',
            'total',
            'available',
            'occupancy',
            'is_verified',
        ]

    def create(self, validated_data):

        room = Room.objects.create(
            building=validated_data['building'],
            title=validated_data['title'],
            rent=validated_data['rent'],
            total=validated_data['total'],
            description=validated_data['description'],
            available=validated_data['available'],
            occupancy=validated_data['occupancy'],
            is_verified=False,
        )
        return room

    def update(self, instance, validated_data):
        instance.title = validated_data.get('title', instance.title)
        instance.rent = validated_data.get('rent', instance.rent)
        instance.description = validated_data.get('description', instance.description)
        instance.occupancy = validated_data.get('occupancy', instance.occupancy)
        instance.save()
        return instance

class PropertyDeedSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField()

    class Meta:
        model = PropertyDeed
        fields = [
            'id',
            'room',
            'owner',
            'registration_no',
            'issue_date',
            'expiry_date',
            'document'
        ]
        validators = [
            UniqueTogetherValidator(queryset=PropertyDeed.objects.all(), fields=['registration_no']),
            UniqueTogetherValidator(queryset=PropertyDeed.objects.all(), fields=['room'])
        ]

    def create(self, validated_data):
        document = None
        if validated_data['document']:
            document = validated_data['document']
            ext = document.name.split('.')[-1]
            document.name = secrets.token_urlsafe(30) + '.' + ext

        property_deed = PropertyDeed.objects.create(
            room=validated_data['room'],
            owner=validated_data['owner'],

            registration_no=validated_data['registration_no'],
            issue_date=validated_data['issue_date'],
            expiry_date=validated_data['expiry_date'],
            document=document
        )
        return property_deed

class BuildingPhotoSerializer(serializers.ModelSerializer):
    class Meta:
        model = BuildingPhoto
        read_only_fields = ['id', 'caption', 'photo']
        fields = ['id', 'caption', 'photo']

class PerkSerializer(serializers.ModelSerializer):
    class Meta:
        model = Perk
        read_only_fields = ['id', 'description']
        fields = ['id', 'description']

class BookingSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField()

    class Meta:
        model = Booking
        read_only_fields = ['id', 'booking_no', 'room', 'user', 'booking_date']
        fields = ['id', 'booking_no', 'room', 'user', 'booking_date']

class BookmarkSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField()

    class Meta:
        model = Bookmark
        fields = [
            'id',
            'user',
            'building'
        ]
        validators = [
            UniqueTogetherValidator(queryset=Bookmark.objects.all(), fields=['user', 'building'])
        ]

    def create(self, validated_data):
        bookmark = Bookmark.objects.create(
            user=validated_data['user'],
            building=validated_data['building']
        )
        return bookmark


#trabalhar com páginas da web
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
#import para tempo de pausa
import pyautogui as tempo
#import para usar teclas
import pyautogui as tecla
#By serve para trabalhar com as atualizações mais recentes
from selenium.webdriver.common.by import By
import xlsxwriter
import os

#autprização para acessar configurações do chrome
navegador = webdriver.Chrome()
navegador.get("https://www.google.com.br/")
tempo.sleep(2)

#---------------------------------------------- DOLAR -------------------------------------------------------#

#Digita na caixa de pesquisa
navegador.find_element(By.NAME, 'q').send_keys('Dolar hoje')
tempo.sleep(2)

#Tecla enter
navegador.find_element(By.NAME, 'q').send_keys(Keys.RETURN)
tempo.sleep(2)

#recebe o XPATH do item na tela e pegamos o primeiro valor da lista
dolar = navegador.find_elements(By.XPATH, '//*[@id="knowledge-currency__updatable-data-column"]/div[1]/div[2]/span[1]')[0].text
print(dolar)

#---------------------------------------------- EURO -------------------------------------------------------#
tempo.sleep(2)

#retorna para a caixa de pesquisa
navegador.find_element(By.NAME, 'q').send_keys("")
tempo.sleep(2)

#apertar tab
tecla.press('tab')
tempo.sleep(2)
#apertar enter para limpar campo de pesquisa
tecla.press('enter')

#Digita na caixa de pesquisa
navegador.find_element(By.NAME, 'q').send_keys('Euro hoje')
tempo.sleep(2)

#Tecla enter
navegador.find_element(By.NAME, 'q').send_keys(Keys.RETURN)
tempo.sleep(2)

#recebe o XPATH do item na tela e pegamos o primeiro valor da lista
euro = navegador.find_elements(By.XPATH, '//*[@id="knowledge-currency__updatable-data-column"]/div[1]/div[2]/span[1]')[0].text
print(euro)

#---------------------------------------------- EXCEL -------------------------------------------------------#

url = "C:\workspace\Python-RPA\secao02\Dolar e Euro.xlsx"
planilha = xlsxwriter.Workbook(url)
cotacao = planilha.add_worksheet()

dolar = dolar.replace(',','.')
euro = euro.replace(',','.')

dolar = float(dolar)
euro = float(euro)

#escreve nas células
cotacao.write("A1","Dolar")
cotacao.write("B1","Euro")
cotacao.write("A2",dolar)
cotacao.write("B2",euro)

planilha.close()

os.startfile(url)


from flask import Flask

from flask_assets import Environment
from flask_assets import Bundle

from config import Config

from flask_sqlalchemy import SQLAlchemy

from flask_migrate import Migrate

from flask_restful import Api

from flask_login import LoginManager

from flask_mail import Mail

app = Flask(__name__)
app.config.from_object(Config)

app.config['MAX_CONTENT_LENGTH'] = 1 * 1024 * 1024
app.config['ALLOWED_EXTENSIONS'] = ['png', 'jpg', 'jpeg']

db = SQLAlchemy(app)
migrate = Migrate(app, db)
api = Api(app)
login = LoginManager(app)
login.login_view = 'get_sign_in'
mail = Mail(app)

assets = Environment(app)

js = Bundle('script/toggle-sign-mode.js',
            'script/check-form.js',
            'script/modal-windows.js',
            'script/main-page.js',
            'script/count-view-product.js',
            'script/show-frequently-asked-question.js',
            'script/marketplace-news-list.js',
            'script/user-question.js',
            filters='jsmin', output='bundle.min.js')
assets.register('js_all', js)

js_vendors = Bundle('lib/jquery/3.4.0/jquery-3.4.0.min.js',
                    'lib/bootstrap/4.3.1/js/bootstrap.min.js',
                    'lib/pace/1.0.2/js/pace.min.js',
                    'lib/fancybox/3.5.7/js/jquery.fancybox.min.js',
                    filters='jsmin', output='vendors.min.js')
assets.register('js_vendors', js_vendors)

css = Bundle('css/main-page.css',
             'css/sign-form.css',
             'css/cart.css',
             'css/popup-window.css',
             'css/profile.css',
             'css/advantage-marketplace.css',
             'css/frequently-asked-questions.css',
             'css/card-item.css',
             filters='cssmin', output='bundle.min.css')
assets.register('css_all', css)

css_vendors = Bundle('lib/pace/1.0.2/css/pace-theme-minimal.css',
                     'lib/fancybox/3.5.7/css/jquery.fancybox.min.css',
                     'lib/bootstrap/4.3.1/css/bootstrap.min.css')
assets.register('css_vendors', css_vendors)

from xcrafter import routes
from xcrafter import models
from xcrafter import server_api


import ubelt as ub
import pytest

def test_auto_dict():
    auto = ub.AutoDict()
    assert 0 not in auto
    auto[0][10][100] = None
    assert 0 in auto
    assert isinstance(auto[0], ub.AutoDict)

def test_auto_dict_to_dict():
    from ubelt.util_dict import AutoDict
    auto = AutoDict()
    auto[1] = 1
    auto['n1'] = AutoDict()
    auto['n1']['n2'] = AutoDict()
    auto['n1']['n2'][2] = 2
    auto['n1']['n2'][3] = 3
    auto['dict'] = {}
    auto['dict']['n3'] = AutoDict()
    auto['dict']['n3']['n4'] = AutoDict()
    print('auto = {!r}'.format(auto))
    static = auto.to_dict()
    print('static = {!r}'.format(static))
    assert not isinstance(static, AutoDict), '{}'.format(type(static))
    assert not isinstance(static['n1'], AutoDict), '{}'.format(type(static['n1']))
    assert not isinstance(static['n1']['n2'], AutoDict)
    assert isinstance(static['dict']['n3'], AutoDict)
    assert isinstance(static['dict']['n3']['n4'], AutoDict)

def test_auto_dict_ordered():
    # To Dict should repsect ordering
    from ubelt.util_dict import AutoOrderedDict, AutoDict
    auto = AutoOrderedDict()
    auto[0][3] = 3
    auto[0][2] = 2
    auto[0][1] = 1
    auto[0][4] = AutoDict()
    assert isinstance(auto, AutoDict)
    print('auto = {!r}'.format(auto))
    static = auto.to_dict()
    print('static = {!r}'.format(static))
    assert not isinstance(static, AutoDict), 'bad cast {}'.format(type(static))
    assert not isinstance(static[0][4], AutoDict), 'bad cast {}'.format(type(static[0][4]))
    assert list(auto[0].values())[0:3] == [3, 2, 1], 'maintain order'

def test_group_items_sorted():
    pairs = [
        ('ham', 'protein'),
        ('jam', 'fruit'),
        ('spam', 'protein'),
        ('eggs', 'protein'),
        ('cheese', 'dairy'),
        ('banana', 'fruit'),
    ]
    item_list, groupid_list = zip(*pairs)
    result1 = ub.group_items(item_list, groupid_list, sorted_=False)
    result2 = ub.group_items(item_list, groupid_list, sorted_=True)
    result1 = ub.map_vals(set, result1)
    result2 = ub.map_vals(set, result2)
    assert result1 == result2

def test_group_items_sorted_mixed_types():
    import random
    groupid_list = [
        1, 2, 3, 1, 2, 3, 1, 2, 3, 1, 2, 3,
        '1', '2', '3', '1', '2', '3', '1', '2', '3', '1', '2', '3',
    ]
    item_list = list(range(len(groupid_list)))

    # Randomize the order
    random.Random(947043).shuffle(groupid_list)
    random.Random(947043).shuffle(item_list)

    result1 = ub.group_items(item_list, groupid_list, sorted_=True)
    result2 = ub.group_items(item_list, groupid_list, sorted_=False)

    result1 = ub.map_vals(set, result1)
    result2 = ub.map_vals(set, result2)
    assert result1 == result2

    assert '1' in result1
    assert 1 in result1

def test_dzip_errors():
    with pytest.raises(TypeError):
        ub.dzip([1], 2)
    with pytest.raises(TypeError):
        ub.dzip(1, [2])
    with pytest.raises(ValueError):
        ub.dzip([1, 2, 3], [])
    with pytest.raises(ValueError):
        ub.dzip([], [4, 5, 6])
    with pytest.raises(ValueError):
        ub.dzip([1, 2, 3], [4, 5])