import logging
from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned
from dotenv import load_dotenv

load_dotenv()

import os
import django
import requests
from math import ceil

django.setup()

from prices.models import *

shop = Shop.objects.get(name='DAJAR')
user_agent = os.environ.get('User-Agent')
headers = {"User-Agent": user_agent}

logging.basicConfig(filename='../app_dajar.log', level=logging.DEBUG, format='%(asctime)s\t%(levelname)s\t%(message)s')

url = "https://dajar.pl/searchengine/pl/V1/products\
?searchCriteria[filter_groups][0][filters][0][field]=category_id\
&searchCriteria[filter_groups][0][filters][0][value]={category_id}\
&searchCriteria[filter_groups][0][filters][0][condition_type]=eq\
&searchCriteria[pageSize]={page_size}\
&searchCriteria[filter_groups][2][filters][0][field]=type_id\
&searchCriteria[filter_groups][2][filters][0][value]=simple\
&searchCriteria[filter_groups][3][filters][0][field]=visibility\
&searchCriteria[filter_groups][3][filters][0][value]=2,4\
&searchCriteria[filter_groups][3][filters][0][condition_type]=in\
&searchCriteria[sortOrders][4][direction]=desc\
&searchCriteria[sortOrders][4][field]=position\
&searchCriteria[sortOrders][5][direction]=desc\
&searchCriteria[sortOrders][5][field]=id\
&searchCriteria[currentPage]={current_page}"

def get_producer(array: []):
    """
    search for producer in array of dict
    """
    for i in array:
        if i.get('attribute_code') == 'producer':
            return i
    return None

def add_dajar_products():
    categories = Category.objects.filter(shop_id=shop)
    for category in categories:
        print(category.shop_category_id)

        req = requests.get(url.format(category_id=category.shop_category_id, page_size=1, current_page=1),
                           headers=headers)

        if req.status_code == 200:
            page_end = ceil(req.json()['total_count'] / 100) + 1
        else:
            page_end = 0
        print("page end: ", page_end, "status code: ", req.status_code)

        for page in range(1, page_end):

            req = requests.get(url.format(category_id=category.shop_category_id, page_size=100, current_page=page),
                               headers=headers)

            print('page: ', page, 'status code: ', req.status_code)
            items = req.json()['items']

            for item in items:

                try:
                    atr = get_producer(item.get("custom_attributes"))
                    brand_id = atr.get('value')
                    brand_name = atr.get('name')
                    brand = ProductBrand.objects.get(shop_product_brand_id=brand_id, shop_id=shop)
                except ObjectDoesNotExist:
                    brand = ProductBrand.objects.create(shop_product_brand_id=brand_id, shop_id=shop,
                                                        brand_name=brand_name)
                except MultipleObjectsReturned:
                    logging.warning(f"brand duplicated: {brand_id}")
                    continue
                except AttributeError:
                    logging.warning(f"Attribute Error brand: {product_id}")
                    continue

                try:
                    product_id = item.get('id')
                    product = Product.objects.get(shop_product_id=product_id, shop_id=shop)
                except ObjectDoesNotExist:
                    product_name = item.get('name')
                    extension_attributes = item.get('extension_attributes')
                    print("extension_attributes: ", extension_attributes)
                    ean = [extension_attributes.get('ean', None)]
                    photo_name = extension_attributes.get("image_dimensions")[0] \
                        .get('product_page_image_small').get('src')
                    photo_url = '//dajarmedia.dajarmedia.com/cdn-cgi/image/width=420,quality=70,format=auto' + photo_name
                    product = Product(shop_product_id=product_id, product_name=product_name, shop_id=shop,
                                      category_id=category, brand_id=brand, ean=ean, photo_url=photo_url)
                    product.save()
                except MultipleObjectsReturned:
                    logging.warning(f'MULTIPLE product_id: {product_id}')
                    continue
                except AttributeError:
                    logging.warning(f"Attribute Error product: {product_id}")
                    continue

                price = item.get('price')
                final_price = item.get('final_price')
                if final_price < price:
                    price_promo = final_price
                else:
                    price_promo = None

                Price.objects.create(product_id=product, price=price, price_promo=price_promo)

if __name__ == '__main__':
    add_dajar_products()


import logging
from typing import List, Tuple

import torch

logger = logging.getLogger(__name__)

class PastKeyValuesHelper:
    """Helper functions to process past key values for encoder-decoder model"""

    @staticmethod
    def get_past_names(num_layers, present: bool = False):
        past_self_names = []
        past_cross_names = []
        for i in range(num_layers):
            past_self_names.extend(
                [f"present_key_self_{i}", f"present_value_self_{i}"]
                if present
                else [f"past_key_self_{i}", f"past_value_self_{i}"]
            )
            past_cross_names.extend(
                [f"present_key_cross_{i}", f"present_value_cross_{i}"]
                if present
                else [f"past_key_cross_{i}", f"past_value_cross_{i}"]
            )
        return past_self_names + past_cross_names

    @staticmethod
    def group_by_self_or_cross(present_key_values):
        """Split present state from grouped by layer to grouped by self/cross attention.
        Before: (past_key_self_0, past_value_self_0, past_key_cross_0, past_value_cross_0), (past_key_self_1, past_value_self_1, past_key_cross_1, past_value_cross_1), ...
        After: (past_key_self_0, past_value_self_0, past_key_self_1, past_value_self_1, ...), (past_key_cross_0, past_value_cross_0, past_key_cross_1, past_value_cross_1, ...)

        """
        present_self = []
        present_cross = []
        for _i, present_layer_i in enumerate(present_key_values):
            assert len(present_layer_i) == 4, f"Expected to have four items. Got {len(present_layer_i)}"
            (
                present_key_self,
                present_value_self,
                present_key_cross,
                present_value_cross,
            ) = present_layer_i
            present_self.extend([present_key_self, present_value_self])
            present_cross.extend([present_key_cross, present_value_cross])
        return present_self, present_cross

    @staticmethod
    def group_by_layer(past, num_layers):
        """Reorder past state from grouped by self/cross attention to grouped by layer.
        Before: past_key_self_0, past_value_self_0, past_key_self_1, past_value_self_1, ..., past_key_cross_0, past_value_cross_0, past_key_cross_1, past_value_cross_1, ...
        After: (past_key_self_0, past_value_self_0, past_key_cross_0, past_value_cross_0), (past_key_self_1, past_value_self_1, past_key_cross_1, past_value_cross_1),
        """
        assert len(past) == 4 * num_layers
        return tuple(
            [
                past[2 * i],
                past[2 * i + 1],
                past[2 * num_layers + 2 * i],
                past[2 * num_layers + 2 * i + 1],
            ]
            for i in range(num_layers)
        )

    @staticmethod
    def back_group_by_layer(past_key_values: Tuple[Tuple[torch.Tensor]]):
        """Categorize present_key_values from self and cross attention to layer by layer.

        Reorder past state from grouped by self/cross attention to grouped by layer.
        Before: past_key_self_0, past_value_self_0, past_key_self_1, past_value_self_1, ...,
                past_key_cross_0, past_value_cross_0, past_key_cross_1, past_value_cross_1, ...
        After: (past_key_self_0, past_value_self_0, past_key_cross_0, past_value_cross_0),
                (past_key_self_1, past_value_self_1, past_key_cross_1, past_value_cross_1),

        Args:
            present_key_values: From past_key_values of a model (group by self and cross attention)

        Returns:
            past_tuples: present key and values grouped by layer.
        """
        past_tuples = ()
        half_idx = len(past_key_values) // 2
        for i in range(len(past_key_values) // 4):
            idx = 2 * i
            past_tuples += (
                (
                    past_key_values[idx],
                    past_key_values[idx + 1],
                    past_key_values[half_idx + idx],
                    past_key_values[half_idx + idx + 1],
                ),
            )
        return past_tuples

    @staticmethod
    def group_by_self_and_cross(present_key_values: Tuple[torch.Tensor], concat: bool = False):
        """Categorize present_key_values into self and cross attention.

        Split present state from grouped by layer to grouped by self/cross attention.
        Before: (past_key_self_0, past_value_self_0, past_key_cross_0, past_value_cross_0),
                (past_key_self_1, past_value_self_1, past_key_cross_1, past_value_cross_1), ...
        After: (past_key_self_0, past_value_self_0, past_key_self_1, past_value_self_1, ...),
                (past_key_cross_0, past_value_cross_0, past_key_cross_1, past_value_cross_1, ...)

        Args:
            present_key_values: From past_key_values of a model (group by layer)
            concat: If concat self attention with cross attention key/value to return

        Returns:
            present_self (Tuple[torch.Tensor]): present key and values from self attention
            present_cross (Tuple[torch.Tensor]): present key and values from cross attention
        """
        present_self: List[torch.Tensor] = []
        present_cross: List[torch.Tensor] = []
        for _, present_layer_i in enumerate(present_key_values):
            assert len(present_layer_i) == 4, f"Expected to have four items. Got {len(present_layer_i)}"
            present_key_self, present_value_self, present_key_cross, present_value_cross = present_layer_i
            present_self.extend([present_key_self, present_value_self])
            present_cross.extend([present_key_cross, present_value_cross])
        if concat:
            return present_self + present_cross
        else:
            return present_self, present_cross

    @staticmethod
    def get_input_names(past_key_values: Tuple[Tuple[torch.Tensor]], encoder=True):
        """Process input names of model wrapper.

        Args:
            past_key_values: Consider `self` and `cross` past_key_values

        Returns:
            names (List[string]): input names
        """
        names = []
        num_layers = len(past_key_values) // 4 if encoder else len(past_key_values)
        prefix = "past_" if not encoder else "present_"
        for i in range(num_layers):
            names.extend([prefix + s for s in [f"key_self_{i}", f"value_self_{i}"]])
        for i in range(num_layers):
            names.extend([prefix + s for s in [f"key_cross_{i}", f"value_cross_{i}"]])
        return names


# A part of NonVisual Desktop Access (NVDA)
# This file is covered by the GNU General Public License.
# See the file COPYING for more details.
# Copyright (C) 2010-2023 Gianluca Casalino, NV Access Limited, Babbage B.V., Leonard de Ruijter,
# Bram Duvigneau

from typing import List

import serial
from io import BytesIO
import hwIo
import braille
from logHandler import log
from collections import OrderedDict
import inputCore
import brailleInput
from baseObject import AutoPropertyObject
import time
import bdDetect

BAUD_RATE = 115200
PARITY = serial.PARITY_NONE

class Model(AutoPropertyObject):
	"""Extend from this base class to define model specific behavior."""
	#: Two bytes device identifier, used in the protocol to identify the device
	#: @type: bytes
	deviceId = b""
	#: A generic name that identifies the model/series, used in gesture identifiers
	#: @type: string
	name = ""
	#: Number of braille cells
	#: @type: int
	numCells = 0 #0 means undefined, needs to be requested for
	#: The USB VID and PID for this model in the form VID_xxxx&PID_xxxx
	#: @type: string
	usbId = ""
	#: The bluetooth prefix used by devices of this specific model
	#: @type: string
	bluetoothPrefix = ""

	def _get_keys(self):
		"""Basic keymap

		This returns a basic keymap with sensible defaults for all devices.
		Subclasses should override or extend this method to add model specific keys,
		or relabel keys. Even if a key isn't available on all devices, add it here
		if it would make sense for most devices.

		The Hims protocol uses a 4 bytes value for key identification.
		Bit shifting is used to make clear what byte is used for what key.
		For example: 0x001 represents a key code that will be received in the first byte,
		0x001<<8 represents a key code that will be received in the second byte, etc.
		"""
		return OrderedDict({
			# Braille keyboard, not used for SyncBraille
			0x01:"dot1",
			0x02:"dot2",
			0x04:"dot3",
			0x08:"dot4",
			0x10:"dot5",
			0x20:"dot6",
			0x40:"dot7",
			0x80:"dot8",
			0x01<<8: "space",
			0x02<<8: "f1",
			0x04<<8: "f2",
			0x08<<8: "f3",
			0x10<<8: "f4",
			0x20<<8: "leftSideScroll",
			0x40<<8: "rightSideScroll",
		})

class BrailleSense(Model):
	name = "Braille Sense"
	usbId = "VID_045E&PID_930A"
	bluetoothPrefix = "BrailleSense"
	numCells = 0 # Either 18 or 32

	def _get_keys(self):
		keys = super(BrailleSense, self)._get_keys()
		keys.update({
			0x01<<16: "leftSideScrollUp",
			0x02<<16: "leftSideScrollDown",
			0x04<<16: "rightSideScrollUp",
			0x08<<16: "rightSideScrollDown",
		})
		return keys

class BrailleEdge(Model):
	deviceId = b"\x42\x45" # BE
	name = "Braille Edge"
	usbId = "VID_045E&PID_930B"
	bluetoothPrefix = "BrailleEDGE"
	numCells = 40

	def _get_keys(self):
		keys = super(BrailleEdge, self)._get_keys()
		keys.update({
			0x01<<16: "leftSideScrollUp",
			0x02<<16: "rightSideScrollUp",
			0x04<<16: "rightSideScrollDown",
			0x08<<16: "leftSideScrollDown",
			0x10<<16: "f5",
			0x20<<16: "f6",
			0x40<<16: "f7",
			0x80<<16: "f8",
			0x01<<24: "leftSideUpArrow",
			0x02<<24: "leftSideDownArrow",
			0x04<<24: "leftSideLeftArrow",
			0x08<<24: "leftSideRightArrow",
			0x10<<24: "rightSideUpArrow",
			0x20<<24: "rightSideDownArrow",
			0x40<<24: "rightSideLeftArrow",
			0x80<<24: "rightSideRightArrow",
		})
		return keys

class BrailleSense2S(BrailleSense):
	"""Braille Sense with one scroll key on both sides.
	Also referred to as Braille Sense Classic."""
	name = "Braille Sense Classic"
	deviceId = b"\x42\x53" # BS

class BrailleSense4S(BrailleSense):
	deviceId = b"\x4c\x58" # LX

class SmartBeetle(BrailleSense4S):
	"""Subclass for Smart Beetle device, which has the same identifier as the Braille Sense with 4 scroll keys.
	However, it is distinguishable by the number of cells.
	Furthermore, the key codes for f2 and f4 are swapped, and it has only two scroll keys.
	"""
	numCells=14
	bluetoothPrefix = "SmartBeetle(b)"
	name = "Smart Beetle"

	def _get_keys(self):
		keys = Model._get_keys(self)
		keys.update({
			0x04<<8: "f4",
			0x10<<8: "f2",
			0x04<<16: "leftSideScroll",
			0x08<<16: "rightSideScroll",
		})
		return keys

class BrailleSenseQ(BrailleSense4S):
	deviceId = b"\x51\x58" # QX
	name = "Braille Sense QWERTY"
	numCells = 32

class BrailleSenseQX(BrailleSenseQ):
	"""Special identifier to support QWERTY input"""
	deviceId = b"\x53\x58" # SX

class SyncBraille(Model):
	name = "SyncBraille"
	usbId = "VID_0403&PID_6001"

	def _get_keys(self):
		return OrderedDict({
			0x10<<8: "leftSideScrollUp",
			0x20<<8: "rightSideScrollUp",
			0x40<<8: "rightSideScrollDown",
			0x80<<8: "leftSideScrollDown",
		})

modelMap = [(cls.deviceId,cls) for cls in (
	# The order of models in this list is important, as some models can simulate other models.
	# For example, the Braille Edge can report itself as a Braille Sense Classic
	BrailleSenseQX,
	BrailleSenseQ,
	BrailleEdge,
	SmartBeetle,
	BrailleSense4S,
	BrailleSense2S,
	SyncBraille,
)]

class BrailleDisplayDriver(braille.BrailleDisplayDriver):
	name = "hims"
	# Translators: The name of a series of braille displays.
	description = _("HIMS Braille Sense/Braille EDGE/Smart Beetle/Sync Braille series")
	isThreadSafe = True
	supportsAutomaticDetection = True
	timeout = 0.2

	@classmethod
	def registerAutomaticDetection(cls, driverRegistrar: bdDetect.DriverRegistrar):
		# Bulk devices
		driverRegistrar.addUsbDevices(bdDetect.KEY_CUSTOM, {
			"VID_045E&PID_930A",  # Braille Sense & Smart Beetle
			"VID_045E&PID_930B",  # Braille EDGE 40
		})

		# Sync Braille, serial device
		driverRegistrar.addUsbDevices(bdDetect.KEY_SERIAL, {
			"VID_0403&PID_6001",
		})

		driverRegistrar.addBluetoothDevices(lambda m: any(m.id.startswith(prefix) for prefix in (
			"BrailleSense",
			"BrailleEDGE",
			"SmartBeetle",
		)))

	@classmethod
	def getManualPorts(cls):
		return braille.getSerialPorts(filterFunc=lambda info: "bluetoothName" in info)

	def __init__(self, port="auto"):
		super(BrailleDisplayDriver, self).__init__()
		self.numCells = 0
		self._model = None

		for match in self._getTryPorts(port):
			portType, portId, port, portInfo = match
			self.isBulk = portType==bdDetect.KEY_CUSTOM
			# Try talking to the display.
			try:
				if self.isBulk:
					# onReceiveSize based on max packet size according to USB endpoint information.
					self._dev = hwIo.Bulk(port, 0, 1, self._onReceive, onReceiveSize=64)
				else:
					self._dev = hwIo.Serial(port, baudrate=BAUD_RATE, parity=PARITY, timeout=self.timeout, writeTimeout=self.timeout, onReceive=self._onReceive)
			except EnvironmentError:
				log.debugWarning("", exc_info=True)
				continue
			for i in range(3):
				self._sendCellCountRequest()
				# Wait for an expected response.
				if self.isBulk:
					# Hims Bulk devices sometimes present themselves to the system while not yet ready.
					# For example, when switching the connection mode toggle on the Braille EDGE from Bluetooth to USB,
					# the USB device is connected but not yet ready.
					# Wait ten times the timeout, which is ugly, but effective.
					self._dev.waitForRead(self.timeout*10)
				else:
					self._dev.waitForRead(self.timeout)
				if self.numCells:
					break
			if not self.numCells:
				log.debugWarning("No response from potential Hims display")
				self._dev.close()
				continue
			self._sendIdentificationRequests(match)
			if self._model:
				# A display responded.
				log.info("Found {device} connected via {type} ({port})".format(
					device=self._model.name, type=portType, port=port))
				break

			self._dev.close()
		else:
			raise RuntimeError("No Hims display found")

	def display(self, cells: List[int]):
		# cells will already be padded up to numCells.
		cellBytes = bytes(cells)
		self._sendPacket(b"\xfc", b"\x01", cellBytes)

	def _sendCellCountRequest(self):
		log.debug("Sending cell count request...")
		self._sendPacket(b"\xfb", b"\x01", bytes(32)) # send 32 null bytes

	def _sendIdentificationRequests(self, match: bdDetect.DeviceMatch):
		log.debug("Considering sending identification requests for device %s"%str(match))
		if match.type==bdDetect.KEY_CUSTOM: # USB Bulk
			matchedModelsMap = [
				modelTuple for modelTuple in modelMap if(
					modelTuple[1].usbId == match.id
				)
			]
		elif "bluetoothName" in match.deviceInfo: # Bluetooth
			matchedModelsMap = [
				modelTuple for modelTuple in modelMap if(
					modelTuple[1].bluetoothPrefix
					and match.id.startswith(modelTuple[1].bluetoothPrefix)
				)
			]
		else: # The only serial device we support which is not bluetooth, is a Sync Braille
			self._model = SyncBraille()
			log.debug("Use %s as model without sending an additional identification request"%self._model.name)
			return
		if not matchedModelsMap:
			log.debugWarning("The provided device match to send identification requests didn't yield any results")
			matchedModelsMap = modelMap
		if len(matchedModelsMap) == 1:
			modelCls = matchedModelsMap[0][1]
			numCells = self.numCells or modelCls.numCells
			if numCells:
				# There is only one model matching the criteria, and we have the proper number of cells.
				# There's no point in sending an identification request at all, just use this model
				log.debug("Use %s as model without sending an additional identification request"%modelCls.name)
				self._model = modelCls()
				self.numCells = numCells
				return
		self._model = None
		for modelId, cls in matchedModelsMap:
			log.debug("Sending request for id %r" % modelId)

			self._dev.write(b"".join([
				b"\x1c",
				modelId,
				b"\x1f"
			]))
			self._dev.waitForRead(self.timeout)
			if self._model:
				log.debug("%s model has been set"%self._model.name)
				break

	def _handleIdentification(self, recvId: bytes):
		modelCls = None
		models = [
			modelCls for modelId, modelCls in modelMap if(
				modelId == recvId
			)
		]
		log.debug("Identification received, id %s" % recvId)
		if not models:
			raise ValueError("Device identification ID unknown in model map")
		if len(models)==1:
			modelCls = models[0]
			self.numCells=self.numCells or modelCls.numCells
			log.debug("There is an exact match, %s found with %d cells"%(modelCls.name,self.numCells))
		elif len(models)>1:
			log.debug("Multiple models match: %s"%", ".join(modelCls.name for modelCls in models))
			try:
				modelCls = next(cls for cls in models if cls.numCells==self.numCells)
				log.debug("There is an exact match out of multiple models, %s found with %d cells"%(modelCls.name,self.numCells))
			except StopIteration:
				log.debugWarning("No exact model match found for the reported %d cells display"%self.numCells)
				try:
					modelCls = next(cls for cls in models if not cls.numCells)
				except StopIteration:
					modelCls = Model
		if modelCls:
			self._model = modelCls()

	def _handlePacket(self, packet: bytes):
		mode = packet[1]
		if mode == 0x00: # Cursor routing
			routingIndex = packet[3]
			try:
				inputCore.manager.executeGesture(RoutingInputGesture(routingIndex))
			except inputCore.NoInputGestureAction:
				pass
		elif mode == 0x01: # Braille input or function key
			if not self._model:
				return
			_keys = int.from_bytes(packet[4:8], "little", signed=False)
			keys = set()
			for keyHex in self._model.keys:
				if _keys & keyHex:
					# This key is pressed
					_keys -= keyHex
					keys.add(keyHex)
					if _keys == 0:
						break
			if _keys:
				log.error("Unknown key(s) 0x%x received from Hims display"%_keys)
				return
			try:
				inputCore.manager.executeGesture(KeyInputGesture(self._model, keys))
			except inputCore.NoInputGestureAction:
				pass
		elif mode == 0x02: # Cell count
			self.numCells = packet[3]

	def _onReceive(self, data: bytes):
		if self.isBulk:
			# data contains the entire packet.
			stream = BytesIO(data)
			firstByte:bytes = data[0:1]
			stream.seek(1)
		else:
			firstByte = data
			# data only contained the first byte. Read the rest from the device.
			stream = self._dev
		if firstByte == b"\x1c":
			# A device is identifying itself
			deviceId: bytes = stream.read(2)
			# When a device identifies itself, the packets ends with 0x1f
			assert stream.read(1) == b"\x1f"
			self._handleIdentification(deviceId)
		elif firstByte == b"\xfa":
			# Command packets are ten bytes long
			packet = firstByte + stream.read(9)
			assert packet[2] == 0x01 # Fixed value
			CHECKSUM_INDEX = 8
			checksum: int = packet[CHECKSUM_INDEX]
			assert packet[9] == 0xfb # Command End
			calcCheckSum: int = 0xff & sum(
				c for index, c in enumerate(packet) if(
					index != CHECKSUM_INDEX)
			)
			assert(calcCheckSum == checksum)
			self._handlePacket(packet)
		else:
			log.debug("Unknown first byte received: 0x%x"%ord(firstByte))
			return

	def _sendPacket(
			self,
			packetType: bytes,
			mode: bytes,
			data1: bytes,
			data2: bytes = b""
	):
		d1Len = len(data1)
		d2Len = len(data2)
		# Construct the packet
		packet: List[bytes] = [
			# Packet start
			packetType * 2,
			# Mode
			mode, # Always "\x01" according to the spec
			# Data block 1 start
			b"\xf0",
			# Data block 1 length
			d1Len.to_bytes(length=2, byteorder="little", signed=False),
			# Data block 1
			data1,
			# Data block 1 end
			b"\xf1",
			# Data block 2 is currently not used, but it is part of the spec
			# Data block 2 start
			b"\xf2",
			# Data block 1 length
			d2Len.to_bytes(length=2, byteorder="little", signed=False),
			# Data block 2
			data2,
			# Data block 2 end
			b"\xf3",
			# Reserved bytes
			b"\x00" * 4,
			# Reserved space for checksum
			# Note that the checksum has the -3rd position in the final packet bytearray,
			# whereas it has the -2nd position in the packet list
			b"\x00",
			# Packet end
			b"\xfd" * 2,
		]
		packetB = bytearray(b"".join(packet))
		#  checksum is the 3rd index from the end because 'packet end' takes up
		# two bytes and 'packetB' is a bytearray
		checksumIndexInPacketB: int = -3
		checksum: int = 0xff & sum(packetB)
		packetB[checksumIndexInPacketB] = checksum

		# check that the packet is the size we expect:
		ptLen = len(packetType)
		assert(ptLen == 1)
		mLen = len(mode)
		assert(mLen == 1)
		packetLength = ptLen*2 + mLen + 1 + 2 + d1Len + 1 + 1 + 2 + d2Len + 1 + 4 + 1 + 2
		assert(len(packetB) == packetLength)

		self._dev.write(bytes(packetB))

	def terminate(self):
		try:
			super(BrailleDisplayDriver, self).terminate()
		finally:
			# We must sleep before closing the port as not doing this can leave the display in a bad state where it can not be re-initialized.
			time.sleep(self.timeout)
			# Make sure the device gets closed.
			# If it doesn't, we may not be able to re-open it later.
			self._dev.close()

	gestureMap = inputCore.GlobalGestureMap({
		"globalCommands.GlobalCommands": {
					"braille_routeTo": (
				"br(hims):routing",
			),
			"braille_scrollBack": (
				"br(hims):leftSideScrollUp",
				"br(hims):rightSideScrollUp",
				"br(hims):leftSideScroll",
			),
			"braille_scrollForward": (
				"br(hims):leftSideScrollDown",
				"br(hims):rightSideScrollDown",
				"br(hims):rightSideScroll",
			),
			"braille_previousLine": (
				"br(hims):leftSideScrollUp+rightSideScrollUp",
			),
			"braille_nextLine": (
				"br(hims):leftSideScrollDown+rightSideScrollDown",
			),
			"review_previousLine": (
				"br(hims):rightSideUpArrow",
			),
			"review_nextLine": (
				"br(hims):rightSideDownArrow",
			),
			"review_previousCharacter": (
				"br(hims):rightSideLeftArrow",
			),
			"review_nextCharacter": (
				"br(hims):rightSideRightArrow",
			),
			"braille_toFocus": (
				"br(hims):leftSideScrollUp+leftSideScrollDown",
				"br(hims):rightSideScrollUp+rightSideScrollDown",
				"br(hims):leftSideScroll+rightSideScroll",
			),
			"kb:control": (
				"br(hims.smartbeetle):f1",
				"br(hims.brailleedge):f3",
			),
			"kb:windows": (
				"br(hims.smartbeetle):f2",
				"br(hims):f7",
			),
			"kb:alt": (
				"br(hims):dot1+dot3+dot4+space",
				"br(hims.smartbeetle):f3",
				"br(hims):f2",
				"br(hims.brailleedge):f4",
			),
			"kb:shift": (
				"br(hims):f5",
			),
			"kb:insert": (
				"br(hims):dot2+dot4+space",
				"br(hims):f6",
			),
			"kb:applications": (
				"br(hims):dot1+dot2+dot3+dot4+space",
				"br(hims):f8",
			),
			"kb:capsLock": (
				"br(hims):dot1+dot3+dot6+space",
			),
			"kb:tab": (
				"br(hims):dot4+dot5+space",
				"br(hims):f3",
				"br(hims.brailleedge):f2",
			),
			"kb:shift+alt+tab": (
				"br(hims):f2+f3+f1",
			),
			"kb:alt+tab": (
				"br(hims):f2+f3",
			),
			"kb:shift+tab": (
				"br(hims):dot1+dot2+space",
			),
			"kb:end": (
				"br(hims):dot4+dot6+space",
			),
			"kb:control+end": (
				"br(hims):dot4+dot5+dot6+space",
			),
			"kb:home": (
				"br(hims):dot1+dot3+space",
				"br(hims.smartbeetle):f4",
			),
			"kb:control+home": (
				"br(hims):dot1+dot2+dot3+space",
			),
			"kb:alt+f4": (
				"br(hims):dot1+dot3+dot5+dot6+space",
			),
			"kb:leftArrow": (
				"br(hims):dot3+space",
				"br(hims):leftSideLeftArrow",
			),
			"kb:control+shift+leftArrow": (
				"br(hims):dot2+dot8+space+f1",
			),
			"kb:control+leftArrow": (
				"br(hims):dot2+space",
			),
			"kb:shift+alt+leftArrow": (
				"br(hims):dot2+dot7+f1",
			),
			"kb:alt+leftArrow": (
				"br(hims):dot2+dot7",
			),
			"kb:rightArrow": (
				"br(hims):dot6+space",
				"br(hims):leftSideRightArrow",
			),
			"kb:control+shift+rightArrow": (
				"br(hims):dot5+dot8+space+f1",
			),
			"kb:control+rightArrow": (
				"br(hims):dot5+space",
			),
			"kb:shift+alt+rightArrow": (
				"br(hims):dot5+dot7+f1",
			),
			"kb:alt+rightArrow": (
				"br(hims):dot5+dot7",
			),
			"kb:pageUp": (
				"br(hims):dot1+dot2+dot6+space",
			),
			"kb:control+pageUp": (
				"br(hims):dot1+dot2+dot6+dot8+space",
			),
			"kb:upArrow": (
				"br(hims):dot1+space",
				"br(hims):leftSideUpArrow",
			),
			"kb:control+shift+upArrow": (
				"br(hims):dot2+dot3+dot8+space+f1",
			),
			"kb:control+upArrow": (
				"br(hims):dot2+dot3+space",
			),
			"kb:shift+alt+upArrow": (
				"br(hims):dot2+dot3+dot7+f1",
			),
			"kb:alt+upArrow": (
				"br(hims):dot2+dot3+dot7",
			),
			"kb:shift+upArrow": (
				"br(hims):leftSideScrollDown+space",
			),
			"kb:pageDown": (
				"br(hims):dot3+dot4+dot5+space",
			),
			"kb:control+pageDown": (
				"br(hims):dot3+dot4+dot5+dot8+space",
			),
			"kb:downArrow": (
				"br(hims):dot4+space",
				"br(hims):leftSideDownArrow",
			),
			"kb:control+shift+downArrow": (
				"br(hims):dot5+dot6+dot8+space+f1",
			),
			"kb:control+downArrow": (
				"br(hims):dot5+dot6+space",
			),
			"kb:shift+alt+downArrow": (
				"br(hims):dot5+dot6+dot7+f1",
			),
			"kb:alt+downArrow": (
				"br(hims):dot5+dot6+dot7",
			),
			"kb:shift+downArrow": (
				"br(hims):space+rightSideScrollDown",
			),
			"kb:escape": (
				"br(hims):dot1+dot5+space",
				"br(hims):f4",
				"br(hims.brailleedge):f1",
			),
			"kb:delete": (
				"br(hims):dot1+dot3+dot5+space",
				"br(hims):dot1+dot4+dot5+space",
			),
			"kb:f1": (
				"br(hims):dot1+dot2+dot5+space",
			),
			"kb:f3": (
				"br(hims):dot1+dot4+dot8+space",
			),
			"kb:f4": (
				"br(hims):dot7+f3",
			),
			"kb:windows+b": (
				"br(hims):dot1+dot2+f1",
			),
			"kb:windows+d": (
				"br(hims):dot1+dot4+dot5+f1",
			),
			"kb:control+insert": (
				"br(hims.smartbeetle):f1+rightSideScroll",
			),
			"kb:alt+insert": (
				"br(hims.smartbeetle):f3+rightSideScroll",
			),
		}
	})

class KeyInputGesture(braille.BrailleDisplayGesture, brailleInput.BrailleInputGesture):

	source = BrailleDisplayDriver.name

	def __init__(self, model, keys):
		super(KeyInputGesture, self).__init__()
		# Model identifiers should not contain spaces.
		self.model=model.name.replace(" ", "")
		self.keys = keys
		self.keyNames = names = set()
		isBrailleInput = True
		for key in keys:
			if isBrailleInput:
				if 0xff & key:
					self.dots |= key
				elif model.keys.get(key)=="space":
					self.space = True
				else:
					# This is not braille input.
					isBrailleInput = False
					self.dots = 0
					self.space = False
			names.add(model.keys[key])

		self.id = "+".join(names)

class RoutingInputGesture(braille.BrailleDisplayGesture):

	source = BrailleDisplayDriver.name

	def __init__(self, routingINdex):
		super(RoutingInputGesture, self).__init__()
		self.routingIndex = routingINdex
		self.id = "routing"


import os
import cv2
import numpy as np
import keras
from keras.preprocessing import image
from keras.preprocessing.image import load_img,img_to_array
from keras.models import load_model
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings("ignore")
def main():
    model=load_model("model.h5")
    face_haar_cascade=cv2.CascadeClassifier(cv2.data.haarcascades+'haarcascade_frontalface_default.xml')
    cap=cv2.VideoCapture(0)
    while True:
        r,test_image=cap.read()
        if not r:
            continue
        grey_image=cv2.cvtColor(test_image,cv2.COLOR_BGR2RGB)
        face_detected=face_haar_cascade.detectMultiScale(grey_image,1.32,5)

        for (x,y,w,h) in face_detected:
            cv2.rectangle(test_image,(x,y),(x+w,y+h),(255,0,0),thickness=7)
            roi_gray=grey_image[y:y+w,x:x+h]
            roi_gray=cv2.resize(roi_gray,(224,224))
            img_px=image.img_to_array(roi_gray)
            img_px=np.expand_dims(img_px,axis=0)
            img_px=img_px/255

            predictions=model.predict(img_px)
            max_index=np.argmax(predictions[0])

            emotions = ('angry', 'disgust', 'fear', 'happy', 'neutral', 'sad', 'surprise')
            predicted_emotion = emotions[max_index]

            cv2.putText(test_image,predicted_emotion,(int(x),int(y)),cv2.FONT_HERSHEY_COMPLEX,1,(0,0,255),2)

        resized_img=cv2.resize(test_image,(1000,700))
        cv2.imshow('Facial emotion:', resized_img)

        if cv2.waitKey(10)==ord('q'):
            break

    cap.release()
    cv2.destroyAllWindows
if __name__=="__main__":
    main()


def calculate_mcd_msd(alpha, fftlen, pool, validation_dir, gt_dir, sr=16000, num_mcep=36, frame_period=5.0):
    converted_dirs = os.listdir(validation_dir)
    total_mcd_list = list()
    f2f_mcd_list = list()
    f2m_mcd_list = list()
    m2f_mcd_list = list()
    m2m_mcd_list = list()
    total_msd_list = list()
    f2f_msd_list = list()
    f2m_msd_list = list()
    m2f_msd_list = list()
    m2m_msd_list = list()
    print(converted_dirs)

    for converted_dir in converted_dirs:
        src, tar = converted_dir.split('_to_')
        if src == tar:
            continue
        converted_dir = os.path.join(validation_dir, converted_dir)
        target_dir = os.path.join(gt_dir, tar)
        sent_list = os.listdir(converted_dir)
        print(sent_list)

        p = Pool(pool)
        converted_mcep_list = p.starmap(load_wav_extract_mcep, zip([converted_dir] * len(sent_list), sent_list))
        target_mcep_list = p.starmap(load_wav_extract_mcep, zip([target_dir] * len(sent_list), sent_list))
        p.close()
        p.join()

        # print('convert')
        # print(len(converted_mcep_list))
        # for d in converted_mcep_list:
        #     print(d.shape)
        # print('target')
        # print(len(target_mcep_list))
        # for d in target_mcep_list:
        #     print(d.shape)
        # print(target_mcep_list[0].shape)
        # print(target_mcep_list[1].shape)
        # print(target_mcep_list[2].shape)

        p = Pool(pool)
        converted_ms_list = p.map(extract_ms, converted_mcep_list)
        target_ms_list = p.map(extract_ms, target_mcep_list)
        p.close()
        p.join()

        p = Pool(pool)
        mcd_list = p.starmap(mcd_cal, zip(converted_mcep_list, target_mcep_list))
        msd_list = p.starmap(msd_cal, zip(converted_ms_list, target_ms_list))
        p.close()
        p.join()

        for mcd, msd, sent in zip(mcd_list, msd_list, sent_list):
            total_mcd_list.append(mcd)
            total_msd_list.append(msd)
            if 'F' in src and 'F' in tar:
                if src == tar:
                    continue
                f2f_mcd_list.append(mcd)
                f2f_msd_list.append(msd)

            elif 'F' in src and 'M' in tar:
                f2m_mcd_list.append(mcd)
                f2m_msd_list.append(msd)

            elif 'M' in src and 'F' in tar:
                m2f_mcd_list.append(mcd)
                m2f_msd_list.append(msd)

            elif 'M' in src and 'M' in tar:
                if src == tar:
                    continue
                m2m_mcd_list.append(mcd)
                m2m_msd_list.append(msd)

        print('SRC: ', src, ' TAR: ', tar, ' MCD_MEAN: ', np.mean(mcd_list), ' MCD_STD: ', np.std(mcd_list))
        print('SRC: ', src, ' TAR: ', tar, ' MSD_MEAN: ', np.mean(msd_list), ' MSD_STD: ', np.std(msd_list))

    print()
    print('-' * 30)
    print('total ', ' MCD_MEAN: ', np.mean(total_mcd_list), ' MCD_STD: ', np.std(total_mcd_list))
    print('f2f ', ' MCD_MEAN: ', np.mean(f2f_mcd_list), ' MCD_STD: ', np.std(f2f_mcd_list))
    print('f2m ', ' MCD_MEAN: ', np.mean(f2m_mcd_list), ' MCD_STD: ', np.std(f2m_mcd_list))
    print('m2f ', ' MCD_MEAN: ', np.mean(m2f_mcd_list), ' MCD_STD: ', np.std(m2f_mcd_list))
    print('m2m ', ' MCD_MEAN: ', np.mean(m2m_mcd_list), ' MCD_STD: ', np.std(m2m_mcd_list))
    print()
    print('-' * 30)
    print('total ', ' MSD_MEAN: ', np.mean(total_msd_list), ' MSD_STD: ', np.std(total_msd_list))
    print('f2f ', ' MSD_MEAN: ', np.mean(f2f_msd_list), ' MSD_STD: ', np.std(f2f_msd_list))
    print('f2m ', ' MSD_MEAN: ', np.mean(f2m_msd_list), ' MSD_STD: ', np.std(f2m_msd_list))
    print('m2f ', ' MSD_MEAN: ', np.mean(m2f_msd_list), ' MSD_STD: ', np.std(m2f_msd_list))
    print('m2m ', ' MSD_MEAN: ', np.mean(m2m_msd_list), ' MSD_STD: ', np.std(m2m_msd_list))

def load_wav_extract_mcep(converted_dir, sent):
    # wav, _ = librosa.load(os.path.join(converted_dir, sent), sr=16000, mono=True)
    _, wav = wavfile.read(os.path.join(converted_dir, sent))
    _, _, sp, _ = world_decompose(wav=wav, fs=16000, frame_period=5.0)
    mcep = pysptk.sp2mc(sp, 36 - 1, 0.455)
    return mcep

def extract_ms(mcep):
    ms = logpowerspec2(4096, mcep)
    return ms

def mcd_cal(converted_mcep, target_mcep):
    converted_mcep = converted_mcep[:,1:]
    target_mcep = target_mcep[:,1:]
    twf = estimate_twf(converted_mcep, target_mcep, fast=True)
    converted_mcep_mod = converted_mcep[twf[0]]
    target_mcep_mod = target_mcep[twf[1]]
    mcd = melcd(converted_mcep_mod, target_mcep_mod)
    return mcd

def msd_cal(converted_ms, target_ms):
    msd = np.sqrt(np.mean(np.power((converted_ms - target_ms), 2)))
    return msd

###############################################
#
#   modified
#
###############################################
def logpowerspec(fftsize, data):
    # create zero padded data
    T, dim = data.shape
    padded_data = np.zeros((fftsize, dim))
    if T > fftsize :
        padded_data += data[:fftsize]
    else:
        padded_data[:T] += data

    complex_spec = np.fft.fftn(padded_data, axes=(0, 1))
    logpowerspec = 2 * np.log(np.absolute(complex_spec))
    return logpowerspec

###############################################
#
#   modified
#
###############################################
def logpowerspec2(fftsize, data):
    # create zero padded data
    T, dim = data.shape
    padded_data = np.zeros((fftsize, dim))

    if T > fftsize :
        padded_data += data[:fftsize]
    else:
        padded_data[:T] += data

    complex_spec = np.fft.rfft(padded_data,fftsize, axis=0)
    R, I = complex_spec.real, complex_spec.imag
    logpowerspec2 = np.log(R * R + I * I)

    return logpowerspec2

def melcd(array1, array2):
    """Calculate mel-cepstrum distortion
    Calculate mel-cepstrum distortion between the arrays.
    This function assumes the shapes of arrays are same.
    Parameters
    ----------
    array1, array2 : array, shape (`T`, `dim`) or shape (`dim`)
        Arrays of original and target.
    Returns
    -------
    mcd : scala, number > 0
        Scala of mel-cepstrum distortion
    """
    if array1.shape != array2.shape:
        raise ValueError(
            "The shapes of both arrays are different \
            : {} / {}".format(array1.shape, array2.shape))

    if array1.ndim == 2:
        # array based melcd calculation
        diff = array1 - array2
        mcd = 10.0 / np.log(10) \
            * np.mean(np.sqrt(2.0 * np.sum(diff ** 2, axis=1)))
    elif array1.ndim == 1:
        diff = array1 - array2
        mcd = 10.0 / np.log(10) * np.sqrt(2.0 * np.sum(diff ** 2))
    else:
        raise ValueError("Dimension mismatch")

    return mcd

def estimate_twf(orgdata, tardata, distance='melcd', fast=True, otflag=None):
    if distance == 'melcd':
        def distance_func(x, y): return melcd(x, y)
    else:
        raise ValueError('other distance metrics than melcd does not support.')

    if otflag is None:
        # use dtw or fastdtw
        if fast:
            _, path = fastdtw(orgdata, tardata, dist=distance_func)
            twf = np.array(path).T

    return twf

import pysptk
import numpy as np
from preprocess import *
from scipy.io import wavfile
from multiprocessing import Pool
from fastdtw import fastdtw
import argparse
import os

alpha = 0.455
############################
#   이거 문제임
############################
fftlen = 4096

parser = argparse.ArgumentParser(description='T')

parser.add_argument('--test_dir', type=str,default='convert/VAE_single')
parser.add_argument('--gt_dir', type=str, default='corpus_seoulNarrative/test')

parser.add_argument('--pool', type=int, help='pool',
                        default=6)

argv = parser.parse_args()
pool = argv.pool

# config for seoulNarr
#   sampling_rate = 16000
#   num_mcep = 36
#   frame_period = 5.0
#   n_frames = 128

calculate_mcd_msd(alpha, fftlen, pool, sr=16000, num_mcep=36, frame_period=5.0, validation_dir=argv.test_dir,
                      gt_dir=argv.gt_dir)


# https://www.youtube.com/watch?v=afITiFR6vfw&index=19&list=PLQVvvaa0QuDfefDfXb9Yf0la1fPDKluPF
import random
import matplotlib.pyplot as plt
from matplotlib import style

style.use('fivethirtyeight')

fig = plt.figure()

def create_plots():
	xs = []
	ys = []

	for i in range(10):
		x = i
		y = random.randrange(10)

		xs.append(x)
		ys.append(y)

	return xs, ys

# add_subplot syntax
'''
# height, width, plot
#ax1 = fig.add_subplot(211)
#ax2 = fig.add_subplot(212)

ax1 = fig.add_subplot(221)
ax2 = fig.add_subplot(222)
ax3 = fig.add_subplot(212)
'''

# 6x1 (6 tall, 1 wide) | (0,0) - start point
#ax1 = plt.subplot2grid((6,1), (0,0), rowspan=2, colspan=1)
#ax2 = plt.subplot2grid((6,1), (2,0), rowspan=2, colspan=1)
#ax3 = plt.subplot2grid((6,1), (4,0), rowspan=2, colspan=1)

ax1 = plt.subplot2grid((6,1), (0,0), rowspan=1, colspan=1)
ax2 = plt.subplot2grid((6,1), (1,0), rowspan=4, colspan=1)
ax3 = plt.subplot2grid((6,1), (5,0), rowspan=1, colspan=1)

x, y = create_plots()
ax1.plot(x, y)

x, y = create_plots()
ax2.plot(x, y)

x, y = create_plots()
ax3.plot(x, y)

plt.show()


from django import template

register = template.Library()

@register.filter
def ru_pluralize(value: int, variants: str) -> str:
    """Фильтр окончаний кириллицы."""
    default = ""
    if not variants:
        return default

    variants = variants.split(",")
    value = abs(int(value))
    if value % 10 == 1 and value % 100 != 11:
        variant = 0
    elif 2 <= value % 10 <= 4 and (value % 100 < 10 or value % 100 >= 20):
        variant = 1
    else:
        variant = 2

    try:
        return variants[variant]
    except IndexError:
        return default


from collections import defaultdict
class Solution:
    def findSubstring(self, s: str, words: List[str]) -> List[int]:
        res = []
        if len(words) == 0: return res
        n = len(s)
        m = len(words)
        w = len(words[0])
        tot = defaultdict(int)
        for word in words: tot[word] += 1
        for i in range(w):
            wd = defaultdict(int)
            cnt = 0
            for j in range(i, n, w):
                if j >= i + m * w:
                    word = s[j - m * w : j - (m - 1) * w]
                    wd[word] -= 1
                    if wd[word] < tot[word]: cnt -= 1
                word = s[j : j + w]
                wd[word] += 1
                if wd[word] <= tot[word]: cnt += 1
                if cnt == m: res.append(j - (m - 1) * w)
        return res


# ALGORITMO DE BUSQUEDA DE ARCHIVOS EN UN SISTEMA DE DIRECOTRIOS, IMPLEMENTNADO NODOS
from operator import le
import pathlib
import os
# from tkinter import Tk, Tcl
# from tkinter.filedialog import askdirectory
# Para archivos
from os.path import isfile, join, isdir

# La dirección completa del archivo .py
camino = pathlib.Path(__file__).parent.absolute()

# def camino():
#   return pathlib.Path(__file__).parent.absolute()
ruta = str(camino)

def elArchivo(url):
  return os.path.split(url) # Devuelve una tupla, el primer elemento es todo lo que viene antes del elementos actual y en sgunda posición seria el componente de la ruta.

def isRuta(url, actual):
  return  url + actual

# FUnción para saber si se trata de un directorio o un archivo
# True: Directorio
# False: archivo
def isDirectorio(dato):
  res = dato.find('.')
  if res == -1:
    return True
  return False

def allContenido(url):
  return os.listdir(url)

def allDirectorios(url, contenido):
  return [nombre for nombre in contenido if isdir(join(url, nombre))]

def allArchivos(url, contenido):
  return [nombre for nombre in contenido if isfile(join(url, nombre))]

def listado_archivos(url):
  arr = allArchivos(url, allContenido(url))
  cantidad = len(arr)
  return [arr, cantidad]

def listado_directorios(url):
  arr = allDirectorios(url, allContenido(url))
  cantidad = len(arr)
  return [arr, cantidad]

# print(type(ruta))
# result = listado_directorios(ruta+'\casi')
# result = listado_archivos(ruta+'\casi')
# print(result)

def todoUrl(url):
  listado = []
  directorio = listado_directorios(url)
  archivo = listado_archivos(url)
  for dic in directorio[0]:
    listado.append(dic)
  for arc in archivo[0]:
    listado.append(arc)

  actual = elArchivo(url)
  return [listado, directorio[0], directorio[1] , archivo[1], actual[1]]

arreglo_hero = []
arreglo_dic = []
arreglo_arc = []
comienzos = []
objetivos = []

def arreglo_maestro(url):
  todo = todoUrl(url)
  comienzos.append(todo[4])
  objetivos.append(todo[0])
  arreglo_dic.append([todo[2]])
  arreglo_arc.append([todo[3]])

  for parte in todo[0]:
    arreglo_hero.append(parte)

  index = 0
  # print(todo[1])
  for par in todo[1]:
    if(index == 0):
      url = isRuta(url, f'\{par}')
      arreglo_maestro(url)
    else:
      new = elArchivo(url)
      url = new[0]
      url = isRuta(url, f'\{par}')
      arreglo_maestro(url)
    index = index + 1

arreglo_maestro(ruta)

# print(arreglo_hero)

nodoInicial = camino.name
num = 0
nodos = {num: nodoInicial}
for nodo in arreglo_hero:
  num = num + 1
  nodos[num]= nodo

num = 0
nodosInvertidos = {nodoInicial: num}
for nodo in arreglo_hero:
  num = num + 1
  nodosInvertidos[nodo]= num

# print('NODOS', nodos)
# print('NODOS INVERTIDOS',nodosInvertidos)

# print('Comienzos', comienzos)
# print('objetivos', objetivos)
# print('.................')
# print(arreglo_dic)
# print(arreglo_arc)

class Grafo:

  def __init__(self, numero_nodos, dirigido=True):
    # Atributos
    self.g_numeros_nodos = numero_nodos
    self.g_nodos = range(self.g_numeros_nodos)
    self.g_dirigido = dirigido
    self.g_adjuntar_lista = {nodo: set() for nodo in self.g_nodos}

  def agregar_borde(self, nodo1, nodo2, peso=1):
    self.g_adjuntar_lista[nodo1].add((nodo2, peso))
    if not self.g_dirigido:
      self.g_adjuntar_lista[nodo2].add((nodo1, peso))

  # Imprimir lista de nodos
  def imprimir_adjuntar_lista(self):
    for clave in self.g_adjuntar_lista.keys(): #
      print(f'nodo{clave}: {self.g_adjuntar_lista[clave]}')

  def busqueda_profundidad(self, inicio, objetivo, camino = [], visitado = set()):
    camino.append(inicio) # Añade el nodo a la lista
    visitado.add(inicio) # Seta el nodo como visitado
    # print(visitado)
    # print(camino)
        # print(camino)
    if inicio == objetivo: # D eser verdadero no hay para que hacer la busqueda
        return camino
    for (puerto, peso) in self.g_adjuntar_lista[inicio]:
        if puerto not in visitado:
            resultado = self.busqueda_profundidad(puerto, objetivo, camino, visitado) # Recursividad
            if resultado is not None:
                return resultado
    camino.pop()
    return None

if __name__ == "__main__":
  cantidad = len(nodos.keys())
  grafo = Grafo(cantidad, dirigido=True)
  count = 0
  for directo in comienzos:
    prin = nodosInvertidos.get(directo)
    # print(prin)
    arr_obj = objetivos[count]
    for puerto in arr_obj:
      sec = nodosInvertidos.get(puerto)
      # print(sec)
      grafo.agregar_borde(prin, sec)
    count = count + 1

  grafo.imprimir_adjuntar_lista()

  ruta = []
  buscar = input('Ingrese su archivo o docuemnto a buscar: ')
  objetivo = nodosInvertidos.get(buscar)
  ruta = grafo.busqueda_profundidad(0, objetivo)
  print(f" La ruta transversal del nodo 0 al nodo 3 es {ruta}")

  new_ruta = []
  for plox in ruta:
    new_ruta.append(nodos.get(plox))
  print(f" La ruta transversal del nodo 0 al nodo 3 es {new_ruta}")


import sys
from flask import (abort, flash, Flask, g, redirect,
                   render_template, request, send_from_directory, session, url_for)
from flask_bootstrap import Bootstrap
from flask_ckeditor import CKEditor

from tinymongo import TinyMongoClient, Query, where
import admin
from gcollections import (demographic_responses_pull, progress_responses_pull, students_from_demog, advisors_from_students, drop_collection)

app = Flask(__name__)
app.secret_key = 'ChangeMeToSomethingSecret'
connection = TinyMongoClient()
DB = connection.biograd
Bootstrap(app)
ckeditor = CKEditor(app)
admin.initialize(app, DB)

# view some raw dictionary from mongo doc as html and form at jinja template
from dict2html import dict2html, dict2form, dict2form_schema, modal_wrapper
# assign filters (pattern)
# app.jinja_env.filters['filtername'] = filterfunc
app.jinja_env.filters['dict2html'] = dict2html
app.jinja_env.filters['dict2form'] = dict2form
app.jinja_env.filters['dict2form_schema'] = dict2form_schema
app.jinja_env.filters['modal_wrapper'] = modal_wrapper

def cli_confirm(prompt):
    """a Y/N confirmation command line prompt"""
    if input(prompt + ' type "CONFIRM" ')=='CONFIRM':
        return True
    return False

def drop_named_collections(db, args):
    """drops ONE collection named in args list
    args is list (typically passed in from sys.argv
    required '--drop'
    list can have 'advisors', 'relationships', 'students'
    """
    idx = args.index('--drop')
    if idx > -1 and idx < len(args):
        for col in args[idx+1:]:
            if cli_confirm('DROP collection "{}"'.format(col)):
                if drop_collection(db, col):
                    print("DROPPED {} collection".format(col))
                else:
                    print("An error was encountered dropping collection")
    sys.exit(0)

def initialize(args):
    # should be "graftable" to initialize function of boilerplate
    pass

@app.before_request
def before_request():
    """should be consistent with boilerplate"""
    g.db = DB
    g.theme = 'united' # bootswatch theme name

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

@app.route('/progress/pull')
def progress_pull():
    """pull progress data from qualtrics and store in db"""
    progress_responses_pull()
    return "see console for results"

@app.route('/demographics/pull')
def demographics_pull():
    """pull demographic data from qualtrics and store in db"""
    demographic_responses_pull()
    return "see console for results"

@app.route('/students/update')
def students_update():
    students_from_demog()
    return "see console for results"

@app.route('/students')
def students_all():
    docs = g.db.students.find({})
    return render_template('student/students_all.html', docs=docs)

@app.route('/student/<sid>')
def student_view(sid):
    schema = [
        ('DEMOG_1_TEXT', 'Firstname'),
        ('DEMOG_2_TEXT', 'Lastname'),
        ('DEMOG_4_TEXT', 'Nickname'),
        ('DEMOG_3_TEXT', 'SID'),
        ('DEMOG_5_TEXT', 'WFU Email'),
        ('DEMOG_6_TEXT', 'Alternate Email')
    ]
    doc = g.db.students.find_one({'DEMOG_3_TEXT':sid})
    if doc:
        relations = g.db.relations.find({'student':doc['_id']})
        advisors = []
        for relation in relations:
            this_advisor = g.db.advisors.find_one({'_id':relation['advisor']})
            if this_advisor and this_advisor['email']:
                advisors.append(this_advisor)

        progress_reports = g.db.progress.find({'DEMOG_3_TEXT':doc['DEMOG_3_TEXT']})
        return render_template('student/student_view.html', doc=doc, schema=schema, advisors=advisors, progress_reports=progress_reports)
    else:
        flash("That student ID did not match any existing records", category="warning")
        return redirect(url_for("students_all"))

@app.route('/advisors/update')
def advisors_update():
    """update advisors from student records"""
    advisors_from_students()
    return redirect(url_for('advisors_all'))

@app.route('/advisors')
def advisors_all():
    """return a view of all advisors"""
    docs = g.db.advisors.find({})
    return render_template('student/generic_docs.html', docs=docs, title="All Advisors")

@app.route('/advisor/update/<id>', methods=['GET','POST'])
def advisor_update(id):
    """modify and advisor"""
    doc = g.db.advisors.find_one({'_id':id})
    if request.method == 'POST':
        form_data = request.form
        fname = request.form.get('fname')
        lname = request.form.get('lname')
        email = request.form.get('email')
        affilliation = request.form.get('affil')
    schema = [('firstname','First Name','firstname'), ('lastname', 'Last Name','lastname'), ('email', 'Email'), ('affiliation', 'Affiliation')]
    return render_template('student/generic_doc_schema_form.html', doc=doc, schema=schema, title='Update Advisor')

@app.route('/advisor/<id>')
def advisor_view(id):
    """advisor view and relationships to students"""
    doc = g.db.advisors.find_one({'_id':id})
    return render_template('student/generic_doc.html', doc=doc, title="Advisor")

@app.route('/advisor_mod/<id>')
def advisor_mod_view(id):
    """advisor view and relationships to students"""
    doc = g.db.advisors.find_one({'_id':id})
    return render_template('student/generic_modal_doc.html', doc=doc, title="Advisor")

@app.route('/progress')
def progress_all():
    """dump all progress responses to screen"""
    docs = g.db.progress.find({})
    return render_template('student/generic_docs.html', docs=docs, title="All Progress Reports")

@app.route('/progress/<id>')
def progress_view(id):
    doc = g.db.progress.find_one({'_id':id})
    return render_template('student/generic_doc.html', doc=doc, title='Progress Report')

@app.route('/demographics')
def demographics_all():
    """dump all demographics to screen"""
    output = []
    docs = g.db.demog.find({})
    return render_template('student/generic_docs.html', docs=docs, title="All Demographic Records")

@app.route('/demographics/sid/<sid>')
def demographics_sid(sid):
    return "todo"

@app.route('/testdict',methods=['GET','POST'])
def testdict():
    doc = {'name':'record collection',
           'count': 3,
           'albums': ['Dark side of the Moon',
                      'Revolver', 'Sgt. Pepper\'s Lonely Hearts Club Band',
                    'Get out of the heat'],
           'person': {"firstname":'Nigel', "lastname":'Tuffnel', 'roles': 'lead guitar, vocals, writer'}
           }
    if request.method == 'POST':
        form_data = request.form
        return render_template('student/generic_doc.html', doc=form_data)
    schema = [('person','Personal Data'), ('separator','-'), ('albums','Albums that are great')]
    return render_template('student/generic_doc_schema_form.html', doc=doc, schema=schema, title='Structure Test')

if __name__ == '__main__':
    if '--initialize' in sys.argv:
        initialize(sys.argv)
    if '--drop' in sys.argv:
        drop_named_collections(DB, sys.argv)
    app.run()


# Databricks notebook source
# MAGIC %md
# MAGIC ##### Welcome  to Azurelib Academy By Deepak Goyal
# MAGIC ##### You can master the Databricks here: www.adeus.azurelib.com
# MAGIC ##### Author of this blog: Arud Seka Berne S in

# COMMAND ----------

# MAGIC %md
# MAGIC #### Pyspark Split Column Values in Azure Databricks

# COMMAND ----------

# MAGIC %md
# MAGIC ###### Gentle reminder:
# MAGIC In Databricks,
# MAGIC   - sparkSession made available as spark
# MAGIC   - sparkContext made available as sc
# MAGIC
# MAGIC In case, you want to create it manually, use the below code.

# COMMAND ----------

from pyspark.sql.session import SparkSession

spark = SparkSession.builder \
    .master("local[*]") \
    .appName("azurelib.com") \
    .getOrCreate()

sc = spark.sparkContext

# COMMAND ----------

# MAGIC %md
# MAGIC ##### a) Create manual PySpark DataFrame

# COMMAND ----------

data = [
    ("Andie,Ebbutt","Andie|Ebbutt|Ebbutt","Andie,Ebbutt Andie|Ebbutt"),
    ("Hobie,Deegan","Hobie|Deegan|Deegan","Hobie,Deegan Hobie|Deegan"),
    ("Denys,Belverstone","Denys|Belverstone|Belverstone","Denys,Belverstone Denys|Belverstone"),
    ("Delphine,Pietersma","Delphine|Pietersma|Pietersma","Delphine,Pietersma Delphine|Pietersma"),
    ("Putnem,Chasson","Putnem|Chasson|Chasson","Putnem,Chasson Putnem|Chasson")
]

df = spark.createDataFrame(data, schema=["names_1","names_2","names_3"])
df.printSchema()
df.show(truncate=False)

# COMMAND ----------

# MAGIC %md
# MAGIC ##### b) Create PySpark DataFrame by reading files

# COMMAND ----------

file_path = "/mnt/practice/name_list.csv"
# replace the file_path with the source file location which you have downloaded.

df_2 = spark.read.format("csv").option("header", True).load(file_path)
df_2.printSchema()

# COMMAND ----------

# MAGIC %md
# MAGIC ##### Note: Here, I will be using the manually created dataframe

# COMMAND ----------

# MAGIC %md
# MAGIC ##### 1. Split() on DataFrame

# COMMAND ----------

from pyspark.sql.functions import split

s_df1 = df.select(split("names_1", ",").alias("comma_delimiter"))
s_df1.printSchema()
s_df1.show(truncate=False)

# COMMAND ----------

# MAGIC %md
# MAGIC ##### 2. Split() using SQL expression

# COMMAND ----------

df.createOrReplaceTempView("names")

spark.sql("SELECT SPLIT(names_1, ',') AS comma_delimiter FROM names") \
.show(truncate=False)

# COMMAND ----------

# MAGIC %md
# MAGIC ##### 3. Split() using limit parameter

# COMMAND ----------

from pyspark.sql.functions import split, size

# 1. Limit = 2
# 2. The resulting array's last entry will contain all the input beyond the last match pattern
# 3. The array length = limit

df.select(
    split("names_2", "\|", limit=2).alias("limit_delimiter"),
    size(split("names_2", "\|", limit=2)).alias("length"),
).show(truncate=False)

# COMMAND ----------

# MAGIC %md
# MAGIC ##### 4. Spliting the column with you have multiple delimiter

# COMMAND ----------

from pyspark.sql.functions import split, size

df.select(
    split("names_3", "[, |]").alias("multiple_delimiter"),
    size(split("names_3", "[, |]")).alias("length"),
).show(truncate=False)

33. Pyspark Split Column Values/Pyspark Split Column Values - Notebook.py


from datetime import timedelta

from airflow import DAG
from airflow.providers.docker.operators.docker import DockerOperator

from airflow.sensors.filesystem import FileSensor
from airflow.utils.dates import days_ago

default_args = {
    "owner": "airflow",
    "email": ["airflow@example.com"],
    "retries": 1,
    "retry_delay": timedelta(minutes=5),
}

with DAG(
        "03_predict_model",
        default_args=default_args,
        schedule_interval="@daily",
        start_date=days_ago(1),
) as dag:
    wait_for_data = FileSensor(
        task_id='wait-for-data',
        poke_interval=10,
        retries=5,
        filepath="data/raw/{{ ds }}/data.csv",
    )
    wait_for_model = FileSensor(
        task_id='wait-for-model',
        poke_interval=10,
        retries=5,
        filepath="data/models/{{ ds }}/model.pkl",
    )
    predict = DockerOperator(
        image="korowood/airflow-predict",
        command="--input-dir /data/raw/{{ ds }} "
                "--output-dir /data/predictions/{{ ds }} "
                "--model-dir data/models/{{ ds }}",
        network_mode="bridge",
        task_id="docker-airflow-predict",
        do_xcom_push=False,
        volumes=["/home/dm/Документы/MADE/2 семетстр/korowood/airflow_ml_dags/data:/data"]
    )

    [wait_for_data, wait_for_model] >> predict


#########################################################################################################################################
############################################################ functions ##################################################################
#                                                                                #
#			-	extract_features(self, file_name): read audio file (based on full path), apply mfcc and return the coefficients                   #
#			-	get_prediction(self, file_name): process audio file and apply model predict                                                       #
#			-	send_msg_osc(self, tag, value): send predicted information via OSC                                                                #
#			-	process_osc_msg(self, unused_addr, args, fileName): get audio file name via OSC, process it, and send the predicted information   #
#			-	startListening(self): put server to wait for OSC messages                                                                         #
#                                                                                #
#########################################################################################################################################

############################################################# imports ####################################################################

# for file/data manipulating
from os import listdir
from os.path import isfile, join
from keras.models import model_from_json
import pandas as pd
import numpy as np

# for MIR functions
import librosa
from sklearn.preprocessing import LabelEncoder
from keras.utils import to_categorical

# to extract notices information
from newsplease import NewsPlease

# for time functions
import time
import datetime

# for OSC functions
from pythonosc import dispatcher
import argparse
from pythonosc import osc_server
from pythonosc import udp_client

########################################################## server main class #################################################################

class OSC_server:

				# constructor to set self variables and start listening
				def __init__(self, n_mfcc, max_pad_len, num_channels, ip, server_port, client_port):

								self.soundPath = "../processing_app/sounds/"
								self.n_mfcc = n_mfcc
								self.max_pad_len = max_pad_len
								self.num_channels = num_channels
								self.ip = ip
								self.server_port = server_port
								self.client_port = client_port

								# load json and create model
								json_file = open('../CNN_emotions/model_saved/model.json', 'r')
								loaded_model_json = json_file.read()
								json_file.close()
								loaded_model = model_from_json(loaded_model_json)

								# load weights into new model
								loaded_model.load_weights("../CNN_emotions/model_saved/model.h5")
								self.model = loaded_model

								# load features to use to get classes
								self.featuresdf = pd.read_pickle('../CNN_emotions/data_processed/featuresData')

								self.dispatcher = dispatcher.Dispatcher()
								self.startListening()

				############################################################# MIR functions ####################################################################
				#---------------------------------------------------------------------------------------------------------------------------------------#
				# this function load the audio and pick their features
				def extract_features(self, file_name):

						try:
								print("\n\n\n\n",file_name)
								# get the audio vector and the sample rate
								y, sr = librosa.load(file_name, res_type='kaiser_fast')

								# get mfcc's vector
								mfccs = librosa.feature.mfcc(y=y, sr=sr, n_mfcc=self.n_mfcc)

								# adjust the size of each audio, according to max_pad_len
								if(mfccs.shape[1]>self.max_pad_len):
										mfccs = mfccs[:,:self.max_pad_len]
								else:
										pad_width = self.max_pad_len - mfccs.shape[1]
										mfccs = np.pad(mfccs, pad_width=((0, 0), (0, pad_width)), mode='constant')

						except Exception as e:
								print("Error encountered while parsing file: ", file_name)
								return None

						return mfccs

				#---------------------------------------------------------------------------------------------------------------------------------------#
				# function to classify the audio
				def get_prediction(self, file_name):

								# extract audio features
								prediction_feature = self.extract_features(self.soundPath + file_name)

								# format input < 1, num_rows, num_columns, num_channels >
								prediction_feature = prediction_feature.reshape(1, self.n_mfcc, self.max_pad_len, self.num_channels)

								# predic the class
								predicted_vector = self.model.predict_classes(prediction_feature)

								# codify the label
								y = np.array(self.featuresdf.class_label.tolist())
								le = LabelEncoder()
								yy = to_categorical(le.fit_transform(y))

								# get predictions
								predicted_class = le.inverse_transform(predicted_vector)
								predicted_proba_vector = self.model.predict_proba(prediction_feature)
								predicted_proba = predicted_proba_vector[0]

								print("The predicted class is:", predicted_class[0])

								# get the % chance of each class
								for i in range(len(predicted_proba)):

												category = le.inverse_transform(np.array([i]))

												print(category[0], "\t : ", format(predicted_proba[i], '.16f') )

								print('\n\n')

								return predicted_class[0], predicted_proba

				########################################################## OSC functions ################################################################
				#---------------------------------------------------------------------------------------------------------------------------------------#
				# function to send the osc message
				def send_msg_osc(self, tag, value):

								# set the ip and port
								parser = argparse.ArgumentParser()
								parser.add_argument("--ip", default=self.ip,
								help="The ip of the OSC server")
								parser.add_argument("--port", type=int, default=self.client_port,
								help="The port the OSC server is listening on")
								args = parser.parse_args()

								# create the UDP cliente and send the message
								client = udp_client.SimpleUDPClient(args.ip, args.port)
								client.send_message(tag, value)

				#---------------------------------------------------------------------------------------------------------------------------------------#
				# function to get msg from client UDP, predict the class name, put it in format (predictionName-%ofFear-%ofHappy-%ofSad) and send via OSC
				def process_osc_msg(self, unused_addr, args, fileName):

								print("Message received: ", fileName)

								predicted_class, predicted_proba = self.get_prediction(fileName)
								oscMsg = "{}-{:.2f}-{:.2f}-{:.2f}".format(predicted_class, predicted_proba[0]*100, predicted_proba[1]*100,   predicted_proba[2]*100)
								print("Sending OSC msg: ", oscMsg)
								# update notices hour per hour
								now = datetime.datetime.now()
								print("Done ( ", now.hour, "h : ", now.minute, "m : ", now.second, "s )!")

								self.send_msg_osc("/prediction", oscMsg)

				#---------------------------------------------------------------------------------------------------------------------------------------#
				# function to put the server waiting for msg's
				def startListening(self):

								# starts the server
								parser = argparse.ArgumentParser()
								parser.add_argument("--ip", default=self.ip, help="The ip to listen on")
								parser.add_argument("--port", type=int, default=self.server_port, help="The port to listen on")
								args = parser.parse_args()

								self.dispatcher.map("/fileName", self.process_osc_msg, "fileName")

								server = osc_server.ThreadingOSCUDPServer((args.ip, args.port), self.dispatcher)
								print("Serving on {}".format(server.server_address))

								server.serve_forever()


''' Basic Face Detection and Eye Detection project'''

import cv2

face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml') #for detecting the face
eye_cascade = cv2.CascadeClassifier('haarcascade_eye_tree_eyeglasses.xml') #for detecting the eyes

first_read = True

cap = cv2.VideoCapture(0) #capture video from the camera/webcam
ret,image = cap.read()

while(ret):
    ret,image = cap.read()
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    gray = cv2.bilateralFilter(gray,5,1,1) #bilateralfilter is used to remove the impurities
    #in the harcascade file. Due to the presence of impurities, Harcascade preformes poorly.
    faces = face_cascade.detectMultiScale(gray,1.3,5,minSize=(200,200)) # It searches for the
    #face frame and keeps on reducing the frame size so that face detection becomes proper and
    #accurate. minsize=(200,200) is the min frame size.

    if(len(faces)>0): #This for loop is for all the faces enclosed within the rectangles
        for x,y,w,h in faces:
            image = cv2.rectangle(image,(x,y),(x+w,y+h),(0,225,0),2) #Draws rectangles arround
            #the face to detect it
            roi_face = gray[y:y+h,x:x+w] #Collects the datapoint from the gray scale image
            roi_face_clr = image[y:y+h,x:x+w] #Collects the datapoint from the coloured image
            eye = eye_cascade.detectMultiScale(roi_face,1.3,5,minSize=(50,50)) #To detect the
            #smaller regions in the face life near the eyes, nose, etc.

            #Main game logic

            if(len(eye)>=2): #If it detects more than two eyes due to framing
                if(first_read): #If the player has not yet started the game
                    cv2.putText(image,"Press s to begin the game. You blink, you lose!",(100,100),cv2.FONT_HERSHEY_PLAIN,3,(0,255,0),2)
                else:
                    print("*****************************************")
            else:
                if(first_read): #If the game is not running
                    cv2.putText(image,"No eyes are detected!",(100,100),cv2.FONT_HERSHEY_PLAIN,3,(0,255,0),2)
                else: #If the game is running
                    print("Ahhh!!!! You blinked. You lost!")
                    first_read = True
    else:
        cv2.putText(image,"No face is detected. Try again.",(100,100),cv2.FONT_HERSHEY_PLAIN,3,(0,255,0),2) #If no face is detected by the system.

    cv2.imshow('image',image)
    w = cv2.waitKey(1)
    if w==ord('q'): #If the user wants ro quit the game by pressing q
        break
    elif(w==ord('s') and first_read): #If the user wants to start the game by pressing s
        first_read = False

cap.release()
cv2.destroyAllWindows()

Stare Game (A basic Face Detection and Eye Detection Project)/stare_game.py


import numpy as np
import matplotlib.pyplot as plt

import rondo
import rondo.functions as F

x = rondo.Variable(np.linspace(-7, 7, 200))
y = F.sin(x)
y.backward(create_graph=True)

logs = [y.data.flatten()]

n = 3
for i in range(n):
    logs.append(x.grad.data.flatten())
    gx = x.grad
    x.cleargrad()
    gx.backward(create_graph=True)

# Draw a graph
labels = ['y=sin(x)', "y'", "y''", "y'''"]
for i, v in enumerate(logs):
    plt.plot(x.data, logs[i], label=labels[i])
plt.legend(loc='lower right')
plt.show()


import numpy as np
import pandas as pd
from flask import Flask, request, jsonify, render_template
import pickle
# import Food_Recommendation_System_Baseline.ipynb
from food_recommendation_system_baseline import foodrecommendation

app = Flask(__name__)
model = pickle.load(open('modelpickel1.pkl', 'rb'))

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

@app.route('/recommend',methods=['POST'])
def predict():
    '''
    For rendering results on HTML GUI
    '''
    # int_features = [x for x in request.for m.values()]
    # print(int_features)
    final_features = request.form['meal']
    print("the input is" + str(final_features))
    prediction = model.give_rec(final_features)
    p = prediction.tolist()
    print(p)
    print("end")

    # output = prediction

    # return render_template('index.html', prediction_text='Employee Salary should be $ {}'.format(output)) .prediction[:5]
    return render_template('index.html', prediction_text='Recommended meals are: ' + "\n".join(p[:5])+ "\n") #+ str(p[:5])

@app.route('/predict_api',methods=['POST'])
def predict_api():
    '''
    For direct API calls trought request
    '''
    data = request.get_json(force=True)
    prediction = model.give_rec(data)

    output = prediction
    return jsonify(output)
    # return ("Success")

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


# --- Import the required variables:
import tweepy
import os

def post_tweet(download_getting: float, download_should_be: float, upload_getting:float, upload_should_be:float):
    """This function will create a tweet to complain about your bad internet speed."""

    # --- Get the required Twitter API keys from O/S environment variables:
    consumer_key = os.environ.get('CONSUMER_KEY', "Test")
    consumer_secret = os.environ.get("CONSUMER_SECRET")
    access_token = os.environ.get("ACCESS_KEY")
    access_token_secret = os.environ.get("ACCESS_SECRET")

    # --- Authenticate with the Twitter API
    client = tweepy.Client(
        consumer_key=consumer_key, consumer_secret=consumer_secret,
        access_token=access_token, access_token_secret=access_token_secret
    )

    # --- Post the tweet:
    response = client.create_tweet(
        text=f"My download speed is: {download_getting}Mbps (should be: {download_should_be}Mbps)\nMy upload speed is: {upload_getting}Mbps (should be: {upload_should_be}Mbps)\n\nPlease Investigate."
    )

    # --- Get the URL for the tweet:
    tweet_link = f"https://twitter.com/user/status/{response.data['id']}"

    # --- Return the URL back to the main.py file:
    return tweet_link


import cv2
import numpy as np

# Define the circle equation and the error function
def circle_eqn(x_c, y_c, x, y):
    return np.sqrt((x-x_c)**2 + (y-y_c)**2)

# Define the error function
def error_fct(params, x, y):
    x_c, y_c, r = params
    return np.sum((circle_eqn(x_c, y_c, x, y) - r)**2)

# Get average of coorinates of point in red tip
def get_red_tip_avg(red_tip):
    red_tip_gray = cv2.cvtColor(red_tip, cv2.COLOR_BGR2GRAY)
    _, red_tip_thresh = cv2.threshold(red_tip_gray, 127, 255, cv2.THRESH_BINARY)
    red_tip_edges = cv2.Canny(red_tip_thresh, 50, 150)
    red_tip_points = np.where((red_tip_edges > 0))
    red_tip_points = np.column_stack((red_tip_points[1], red_tip_points[0]))

    # Get average of coorinates of point in red tip
    red_tip_x = red_tip_points[:, 0]
    red_tip_y = red_tip_points[:, 1]
    x_tip = np.mean(red_tip_x)
    y_tip = np.mean(red_tip_y)

    return x_tip, y_tip

# Compute arc length
def compute_arc_length(x_c, y_c, radius, x_base, y_base, x_tip, y_tip):
    theta_base = np.arctan2(y_base - y_c, x_base - x_c)
    theta_tip = np.arctan2(y_tip - y_c, x_tip - x_c)
    dtheta = np.abs(theta_tip - theta_base)
    dtheta = np.min([dtheta, 2*np.pi - dtheta])  # Ensure the angle is at most pi
    arc_length = radius * dtheta

    return arc_length


#! /usr/bin/env python3
import json
import sys
import requests

def main():
    r = requests.get('https://raw.githubusercontent.com/microsoft/mstic/master/PublicFeeds/ThreatActorNaming/MicrosoftMapping.json')
    r.raise_for_status()
    d = json.loads(r.text)
    search_term = sys.argv[1].lower()
    for item in d:
        for k,v in item.items():
            if isinstance(v, list):
                for i in v:
                    if search_term in i.lower():
                        print(json.dumps(item))
            elif search_term in v.lower():
                print(json.dumps(item))

if __name__ == "__main__":
    main()


#from hubs.hinting import hint, prefixed as _
from hubs.widgets.base import argument
from hubs.widgets.chrome import panel

from hubs import validators

import hubs.models

from fedmsg.meta.base import BaseConglomerator as BC

import jinja2

chrome = panel('Hubs', key='associations')
template = jinja2.Template("""
{% if associations %}
    {% if memberships %}

Belongs to: {{memberships_text}}

    {% endif %}

    {% if subscriptions %}

Subscribes to: {{subscriptions_text}}

    {% endif %}
{% endif %}
""")

@argument(name="username",
          default=None,
          validator=validators.username,
          help="A FAS username.")
def data(session, widget, username):
    user = hubs.models.User.by_username(session, username)
    ownerships = [u.name for u in user.ownerships]
    memberships = [u.name for u in user.memberships]
    subscriptions = [u.name for u in user.subscriptions]
    return dict(
        associations=memberships + ownerships,
        ownerships=ownerships,
        memberships=memberships,
        subscriptions=subscriptions,
        ownerships_text=BC.list_to_series(ownerships),
        memberships_text=BC.list_to_series(memberships),
        subscriptions_text=BC.list_to_series(subscriptions),
    )

def should_invalidate(message, session, widget):
    raise NotImplementedError()


from typing import List

class Solution:
    def addSpaces(self, s: str, spaces: List[int]) -> str:
        x = s
        for i in range(len(spaces)):
            x = x[:spaces[i]+i]+' '+x[spaces[i]+i:]
        return x

#Exercise: https://leetcode.com/problems/adding-spaces-to-a-string/
#You are given a 0-indexed string s and a 0-indexed integer array spaces that describes
# the indices in the original string where spaces will be added. Each space should
# be inserted before the character at the given index.