Untitled

 avatar
unknown
python
2 years ago
4.4 kB
6
Indexable
from xml.etree import ElementTree
from typing import TypeVar
from io import BytesIO

from svglib.svglib import svg2rlg
from reportlab.graphics import renderPM

from alerts_in_ua.location import Location
from alerts_in_ua.map_style import MapStyle, BasicMapStyle


Self = TypeVar("Self")


ukraine_map_keys = {
    "Автономна Республіка Крим": "UKR283",
    "Миколаївська область": "UKR284",
    "Чернігівська область": "UKR285",
    "Рівненська область": "UKR286",
    "Чернівецька область": "UKR288",
    "Івано-Франківська область": "UKR289",
    "Хмельницька область": "UKR290",
    "Львівська область": "UKR291",
    "Тернопільська область": "UKR292",
    "Закарпатська область": "UKR293",
    "Волинська область": "UKR318",
    "Черкаська область": "UKR319",
    "Кіровоградська область": "UKR320",
    "Київська область": "UKR321",
    "Одеська область": "UKR322",
    "Вінницька область": "UKR323",
    "Житомирська область": "UKR324",
    "Сумська область": "UKR325",
    "Дніпропетровська область": "UKR326",
    "Донецька область": "UKR327",
    "Харківська область": "UKR328",
    "Луганська область": "UKR329",
    "Полтавська область": "UKR330",
    "Запорізька область": "UKR331",
    "Херсонська область": "UKR4827",
    "м. Київ": "UKR4826",
    "м. Севастополь": "UKR5482"
}


class Locations(list):
    """
    Список для місць з тревогою для більш зручної маніпуляції над ними
    """

    def __init__(self, *__locations: Location, disclaimer: str, last_updated_at: str) -> None:
        super(Locations, self).__init__(__locations)

        self.disclaimer = disclaimer
        self.last_updated_at = last_updated_at
        self.type = "full"  # Ну тому що v1

    def __getattr__(self, item) -> list:
        return [getattr(location, item) for location in self]

    def append(self, __location: Location) -> None:
        super(Locations, self).append(__location)

    def remove(self, __location: Location) -> None:
        super(Locations, self).remove(__location)

    def filter(self, **filters) -> Self:
        """
        Повертає список місць які підпадають під вказані фільтри

        :param filters: Фільтри
        """

        def location_filter(location: Location) -> bool:
            for filter_name in filters:
                if getattr(location, filter_name) != filters[filter_name]:
                    return False
            return True

        return Locations(
            *list(filter(location_filter, self)),
            disclaimer=self.disclaimer,
            last_updated_at=self.last_updated_at
        )

    def __build_map(self) -> BytesIO:
        svg_ukraine_map = BytesIO()

        with open("../alerts_in_ua/src/map/Ukraine.svg", "r") as file:
            svg_ukraine_map.write(bytes(file.read(), "utf-8"))
            svg_ukraine_map.seek(0)

        ukraine_map = ElementTree.parse(svg_ukraine_map)
        ukraine_map_root = ukraine_map.getroot()

        for _location in self:
            if _location.location_title in ukraine_map_keys:
                key = ukraine_map_keys[_location.location_title]

                for children in ukraine_map_root:
                    if children.attrib["id"] == key:
                        children.set("fill", "#ea4c41")
                        break

        ukraine_map.write(svg_ukraine_map)
        svg_ukraine_map.seek(0)

        return svg_ukraine_map

    def render_map(self, map_style: MapStyle = BasicMapStyle) -> BytesIO:
        svg_ukraine_map = self.__build_map()
        alerts_map = BytesIO()

        alerts_map.write(renderPM.drawToString(svg2rlg(svg_ukraine_map), fmt="PNG"))
        alerts_map.seek(0)

        return alerts_map
Editor is loading...