import xml.etree.ElementTree as ET
from typing import List

import pandas as pd
import matplotlib.pyplot as plt

from mplsoccer import Radar, FontManager, grid

from constants import UNDEFINED_INT
from player import Player
from team import Team

class MatchResults:

    """
    Class constructor that initializes instance variables and calls a function to parse Opta F9 xml file data

    Parameters:
    file_path (str): The path to the Opta F9 xml file that contains the data
    """
    def __init__(self, file_path):
        self.__teams = []
        self.__players = []
        self.__players_stats = []
        self.__all_stat_types_set = set()
        self.__parse_f9opta_file(file_path)

    def get_df_players_stats(self):
        df = pd.DataFrame.from_dict(self.__players_stats)
        return df

    def get_df_all_stats(self):
        return pd.DataFrame(self.__all_stat_types_set, columns = ['stat'])

    def get_df_players(self):
        return pd.DataFrame([{'player_id': p.player_id, 'team_id': p.team_id,
                            'match_position': p.match_position, 'first': p.first,
                            'last': p.last, 'known': p.known} for p in self.__players])

    def get_df_teams(self):
        """
        Returns a pandas DataFrame with information about the teams that played the match.

        Each row of the DataFrame corresponds to a team, and contains the team's
        identifier and name.

        Returns:
            A pandas DataFrame with columns 'team_id' and 'team_name'.
        """
        return pd.DataFrame([{'team_id': t.team_id, 'team_name': t.team_name} for t in self.__teams])

    def get_df_specific_stat(self, stat, player_id = UNDEFINED_INT, team_id = UNDEFINED_INT):
        min_columns = ['player_id', 'team_id', 'match_position', 'first', 'last', 'known',
                        'shirt_number', 'status', 'captain', 'mins_played', stat]
        df = self.get_df_players_stats().loc[:, min_columns]
        if player_id != UNDEFINED_INT:
            df = df.query(f'player_id == {player_id}').reset_index(drop=True)
        if team_id != UNDEFINED_INT:
            df = df.query(f'team_id == {team_id}').reset_index(drop=True)

        return df.sort_values(by=[stat], ascending=False)

    def create_player_radar(self, player_id, list_params,
                        min_minutes = 1, normalized_to_90 = False):
        # radar params
        params = self.__reduce_params(list_params)
        # "lower number is better" list
        lower_is_better_list = self.__get_keys_value_zero(list_params)

        # Player stats dataframe (players with more than {min_minutes} minutes played)
        df = self.get_df_players_stats()
        df_mins = df.query(f'mins_played >= {min_minutes}').reset_index(drop=True)

        if len(df_mins.query(f'player_id == {player_id}')) == 0:
            raise("The selected player did not play the defined minimum number of minutes")

        low_values, high_values = self.__calculate_low_high_values(df_mins, params,
                                            normalized_to_90 = normalized_to_90)
        player_values = self.__calculate_player_values(df_mins, params, player_id,
                                            normalized_to_90 = normalized_to_90)

        # creating the figure using the grid function from mplsoccer:
        fig, axs = grid(figheight=14, grid_height=0.915, title_height=0.06, endnote_height=0.025,
                        title_space=0, endnote_space=0, grid_key='radar', axis=False)

        radar = Radar(params, low_values, high_values,
              lower_is_better=lower_is_better_list,
              round_int=[False]*len(params),
              num_rings=4,
              ring_width=1, center_circle_radius=1)

        # Plot radar
        radar.setup_axis(ax=axs['radar'])
        rings_inner = radar.draw_circles(ax=axs['radar'], facecolor='#6fa8dc', edgecolor='#2c4358')
        radar_output = radar.draw_radar(player_values, ax=axs['radar'],
                                        kwargs_radar={'facecolor': '#dca36f'},
                                        kwargs_rings={'facecolor': '#66d8ba'})
        radar_poly, rings_outer, vertices = radar_output
        range_labels = radar.draw_range_labels(ax=axs['radar'], fontsize=12)
        param_labels = radar.draw_param_labels(ax=axs['radar'], fontsize=12)
        axs['radar'].scatter(vertices[:, 0], vertices[:, 1], c='#00f2c1', edgecolors='#6d6c6d',
                                marker='o', s=40, zorder=2)

        # Legends
        # Player info
        obj_player = self.__get_player(player_id)
        obj_team = self.__get_team(UNDEFINED_INT if obj_player is None else obj_player.team_id)
        player_name = "" if obj_player is None else f"{obj_player.first} {obj_player.last}"
        player_team_name = "" if obj_team is None else obj_team.team_name
        title1_text = axs['title'].text(0.04, 0.65, player_name, fontsize=16,
                                        ha='left', va='center')
        title2_text = axs['title'].text(0.90, 0.65, player_team_name, fontsize=14,
                                        ha='right', va='center')
        # Endnote
        min_minutes_text = f"Players who played at least {min_minutes} minutes."
        normalized_text = "Values normalized to 90 mins." if normalized_to_90 else "Absolute values."
        endnote_text = f"INFO: {min_minutes_text}{normalized_text}"
        endnote_text = axs['endnote'].text(0.04, 0.5, endnote_text, fontsize=10,
                                   ha='left', va='center')

        return plt

    def create_comparison_radar(self, player1_id, player2_id, list_params,
                        min_minutes = 1, normalized_to_90 = False):
        # radar params
        params = self.__reduce_params(list_params)
        # "lower number is better" list
        lower_is_better_list = self.__get_keys_value_zero(list_params)

        # Player stats dataframe (players with more than 0 minutes played)
        df = self.get_df_players_stats()
        df_mins = df.query(f'mins_played >= {min_minutes}').reset_index(drop=True)

        if len(df_mins.query(f'player_id == {player1_id}')) == 0 or \
            len(df_mins.query(f'player_id == {player2_id}')) == 0:
            raise("One of the selected players did not play the defined minimum number of minutes")
        low_values, high_values = self.__calculate_low_high_values(df_mins, params,
                                            normalized_to_90 = normalized_to_90)
        player1_values = self.__calculate_player_values(df_mins, params, player1_id,
                                            normalized_to_90 = normalized_to_90)
        player2_values = self.__calculate_player_values(df_mins, params, player2_id,
                                            normalized_to_90 = normalized_to_90)

        radar = Radar(params, low_values, high_values,
              lower_is_better=lower_is_better_list,
              round_int=[False]*len(params),
              num_rings=4,
              ring_width=1, center_circle_radius=1)

        # creating the figure using the grid function from mplsoccer:
        fig, axs = grid(figheight=14, grid_height=0.915, title_height=0.06, endnote_height=0.025,
                title_space=0, endnote_space=0, grid_key='radar', axis=False)

        # plot radar
        radar.setup_axis(ax=axs['radar'])  # format axis as a radar
        rings_inner = radar.draw_circles(ax=axs['radar'], facecolor='#ffb2b2', edgecolor='#fc5f5f')
        radar_output = radar.draw_radar_compare(player1_values, player2_values, ax=axs['radar'],
                                                kwargs_radar={'facecolor': '#00f2c1', 'alpha': 0.6},
                                                kwargs_compare={'facecolor': '#d80499', 'alpha': 0.6})
        radar_poly, radar_poly2, vertices1, vertices2 = radar_output
        range_labels = radar.draw_range_labels(ax=axs['radar'], fontsize=12)
        param_labels = radar.draw_param_labels(ax=axs['radar'], fontsize=12)
        axs['radar'].scatter(vertices1[:, 0], vertices1[:, 1],
                            c='#00f2c1', edgecolors='#6d6c6d', marker='o', s=40, zorder=2)
        axs['radar'].scatter(vertices2[:, 0], vertices2[:, 1],
                            c='#d80499', edgecolors='#6d6c6d', marker='o', s=40, zorder=2)
        # Legend
        obj_player1 = self.__get_player(player1_id)
        obj_player2 = self.__get_player(player2_id)
        obj_team1 = self.__get_team(UNDEFINED_INT if obj_player1 is None else obj_player1.team_id)
        obj_team2 = self.__get_team(UNDEFINED_INT if obj_player2 is None else obj_player2.team_id)
        player1_name = "" if obj_player1 is None else f"{obj_player1.first} {obj_player1.last}"
        player1_team_name = "" if obj_team1 is None else obj_team1.team_name
        player2_name = "" if obj_player2 is None else f"{obj_player2.first} {obj_player2.last}"
        player2_team_name = "" if obj_team2 is None else obj_team2.team_name
        title1_text = axs['title'].text(0.01, 0.65, player1_name, fontsize=16, color='#01c49d',
                                        ha='left', va='center')
        title2_text = axs['title'].text(0.01, 0.25, player1_team_name, fontsize=10,
                                        ha='left', va='center', color='#01c49d')
        title3_text = axs['title'].text(0.99, 0.65, player2_name, fontsize=16,
                                        ha='right', va='center', color='#d80499')
        title4_text = axs['title'].text(0.99, 0.25, player2_team_name, fontsize=10,
                                        ha='right', va='center', color='#d80499')
        return plt

    def __parse_f9opta_file(self, file_path):
        tree = ET.parse(file_path)
        root = tree.getroot()

        list_team_tag = root.findall('.//Team')
        for team_tag in list_team_tag:
            obj_team = self.__parse_team_tag(team_tag)
            self.__teams.append(obj_team)
            for player_tag in team_tag.iter('Player'):
                obj_player = self.__parse_player_tag(player_tag, obj_team.team_id)
                self.__players.append(obj_player)

        list_team_data_tag = root.findall('.//MatchData/TeamData')
        for team_data_tag in list_team_data_tag:
            player_lineup_tag = team_data_tag.find('PlayerLineUp')
            for match_player_tag in player_lineup_tag.iter('MatchPlayer'):
                obj_match_player = self.__parse_match_player_tag(match_player_tag)
                self.__players_stats.append(obj_match_player)
        #adjust player stats with all stats
        self.__adjust_player_stats()

    def __parse_team_tag(self, team_tag):
        id = self.__tag_value_to_int(team_tag.get('uID')[1:])
        name = self.__tag_value_to_str(team_tag.find('Name').text)
        return Team(team_id=id, team_name=name)

    def __parse_player_tag(self, player_tag, team_id):
        id = self.__tag_value_to_int(player_tag.get('uID')[1:])
        match_position = self.__tag_value_to_str(player_tag.get('Position'))
        first_tag = player_tag.find('.//First')
        last_tag = player_tag.find('.//Last')
        known_tag = player_tag.find('.//Known')
        first = self.__tag_value_to_str(None if first_tag is None else first_tag.text)
        last = self.__tag_value_to_str(None if last_tag is None else last_tag.text)
        known = self.__tag_value_to_str(None if known_tag is None else known_tag.text)
        return Player(player_id=id, team_id=team_id, match_position=match_position,
                        first=first, last=last, known=known)

    def __parse_match_player_tag(self, match_player_tag):
        id = self.__tag_value_to_int(match_player_tag.get('PlayerRef')[1:])
        match_position = self.__tag_value_to_str(match_player_tag.get('Position'))
        shirt_number = self.__tag_value_to_int(match_player_tag.get('ShirtNumber'))
        status = self.__tag_value_to_str(match_player_tag.get('Status'))
        captain = self.__tag_value_to_int(match_player_tag.get('Captain'), error_value=0)
        player = next(filter(lambda p: p.player_id == id, self.__players))
        dict_player = {'player_id':id, 'team_id': player.team_id, 'match_position': match_position,
                        'first': player.first, 'last': player.last, 'known': player.known,
                        'shirt_number': shirt_number, 'status': status, 'captain': captain}
        for stat_tag in match_player_tag.iter('Stat'):
            stat_type = self.__tag_value_to_str(stat_tag.get('Type'))
            stat_value = self.__tag_value_to_int(stat_tag.text, error_value=0)
            dict_player.update({stat_type:stat_value})
            self.__all_stat_types_set.add(stat_type)
        return dict_player

    def __adjust_player_stats(self):
        for player_stats in self.__players_stats:
            for stat_type in self.__all_stat_types_set:
                if stat_type not in player_stats:
                    player_stats.update({stat_type: 0})

    def __get_player(self, player_id):
        filtered = [pl for pl in self.__players if pl.player_id == player_id]
        if len(filtered) == 0:
            return None
        else:
            return filtered[0]

    def __get_team(self, team_id):
        filtered = [t for t in self.__teams if t.team_id == team_id]
        if len(filtered) == 0:
            return None
        else:
            return filtered[0]

    @staticmethod
    def __tag_value_to_int(value, error_value = UNDEFINED_INT):
        try:
            return int(value)
        except (ValueError, TypeError):
            return error_value

    @staticmethod
    def __tag_value_to_str(value):
        if value is None:
            return ''
        return str(value)

    @staticmethod
    def __reduce_params(list_params):
        return list(map(lambda d: list(d.keys())[0], list_params))

    @staticmethod
    def __get_keys_value_zero(list_params):
        return list(map(lambda d: list(d.keys())[0],
                    filter(lambda d: d[list(d.keys())[0]] == 0, list_params)))

    @staticmethod
    def __calculate_low_high_values(df, list_params, normalized_to_90 = False):
        df_copy = df.copy()
        low_values = []
        high_values = []
        for param in list_params:
            if normalized_to_90:
                df_copy[param] = df_copy.apply(lambda x: 90 * x[param] / x['mins_played'], axis=1)
            low_values.append(df_copy[param].min())
            high_values.append(df_copy[param].max())
        return low_values, high_values

    @staticmethod
    def __calculate_player_values(df, list_params, player_id, normalized_to_90 = False):
        df_copy = df.copy()
        player_values = []
        for param in list_params:
            if normalized_to_90:
                df_copy[param] = df_copy.apply(lambda x: 90 * x[param] / x['mins_played'], axis=1)
            player_values.append(df_copy.loc[df_copy['player_id'] == player_id, param].iloc[0])
        return player_values


import dbus
import dbus.service

import xl.trax
import xl.event
from xl import player

import mpris_tag_converter

INTERFACE_NAME = 'org.freedesktop.MediaPlayer'

class ExaileMprisTrackList(dbus.service.Object):

    """
        /TrackList object methods
    """

    def __init__(self, exaile, bus):
        dbus.service.Object.__init__(self, bus, '/TrackList')
        self.exaile = exaile
        self.tag_converter = mpris_tag_converter.ExaileTagConverter(exaile)
        for event in ('tracks_removed', 'tracks_added'):
            xl.event.add_callback(self.tracklist_change_cb, event)

    def __get_playlist(self):
        """
            Returns the list of tracks in the current playlist
        """
        return player.QUEUE.current_playlist.get_ordered_tracks()

    @dbus.service.method(INTERFACE_NAME,
            in_signature="i", out_signature="a{sv}")
    def GetMetadata(self, pos):
        """
            Gives all meta data available for element at given position in the
            TrackList, counting from 0

            Each dict entry is organized as follows
              * string: Metadata item name
              * variant: Metadata value
        """
        track = self.__get_playlist()[pos]
        return self.tag_converter.get_metadata(track)

    @dbus.service.method(INTERFACE_NAME, out_signature="i")
    def GetCurrentTrack(self):
        """
            Return the position of current URI in the TrackList The return
            value is zero-based, so the position of the first URI in the
            TrackList is 0. The behavior of this method is unspecified if
            there are zero elements in the TrackList.
        """
        try:
            return player.QUEUE.current_playlist.index(
                    player.PLAYER.current)
        except ValueError:
            return -1

    @dbus.service.method(INTERFACE_NAME, out_signature="i")
    def GetLength(self):
        """
            Number of elements in the TrackList
        """
        return len(player.QUEUE.current_playlist)

    @dbus.service.method(INTERFACE_NAME,
            in_signature="sb", out_signature="i")
    def AddTrack(self, uri, play_immediately):
        """
            Appends an URI in the TrackList.
        """
        uri = uri[7:]
        track = self.exaile.collection.get_track_by_loc(unicode(uri))
        if track is None:
            track = xl.trax.Track(uri)
        player.QUEUE.current_playlist.add(track)
        if play_immediately:
            player.QUEUE.play(track)
        return 0

    @dbus.service.method(INTERFACE_NAME, in_signature="i")
    def DelTrack(self, pos):
        """
            Appends an URI in the TrackList.
        """
        player.QUEUE.current_playlist.remove(pos)

    @dbus.service.method(INTERFACE_NAME, in_signature="b")
    def SetLoop(self, loop):
        """
            Sets the player's "repeat" or "loop" setting
        """
        player.QUEUE.current_playlist.set_repeat(loop)

    @dbus.service.method(INTERFACE_NAME, in_signature="b")
    def SetRandom(self, random):
        """
            Sets the player's "random" setting
        """
        player.QUEUE.current_playlist.set_random(random)

    def tracklist_change_cb(self, type, object, data):
        """
            Callback for a track list change
        """
        len = self.GetLength()
        self.TrackListChange(len)

    @dbus.service.signal(INTERFACE_NAME, signature="i")
    def TrackListChange(self, num_of_elements):
        """
            Signal is emitted when the "TrackList" content has changed:
              * When one or more elements have been added
              * When one or more elements have been removed
              * When the ordering of elements has changed

            The argument is the number of elements in the TrackList after the
            change happened.
        """
        pass


import glob
import os.path

import cv2
import numpy as np
import torch
import torchvision.transforms as transforms
from torch.utils import data

from util.util import get_surface_normals

class KITTIDataset(data.Dataset):
    def __init__(self, opt):
        super().__init__()
        self.image_list = None
        self.opt = opt
        self.batch_size = opt.batch_size
        self.use_surface_normal = opt.use_sne
        self.root = opt.data_root
        self.num_labels = 2
        self.use_size = (opt.resize_width, opt.resize_height)
        if self.use_surface_normal:
            pass
        if opt.phase == "train":
            self.image_list = sorted(glob.glob(os.path.join(self.root, 'training', 'image_2', '*.png')))
        elif opt.phase == "val":
            self.image_list = sorted(glob.glob(os.path.join(self.root, 'validation', 'image_2', '*.png')))
        else:
            self.image_list = sorted(glob.glob(os.path.join(self.root, 'testing', 'image_2', '*.png')))

    def __getitem__(self, index):
        use_dir = "/".join(self.image_list[index].split('\\')[:-2])
        name = self.image_list[index].split('\\')[-1][:-4]

        rgb_image = cv2.cvtColor(cv2.imread(os.path.join(use_dir, 'image_2', name + ".png")), cv2.COLOR_BGR2RGB)
        depth_image = cv2.imread(os.path.join(use_dir, 'depth2', name + ".png"), cv2.IMREAD_ANYDEPTH)
        orig_height, orig_width, _ = rgb_image.shape
        if self.opt.phase == 'test' and self.opt.no_label:
            label = np.zeros((orig_height, orig_width), dtype=np.uint8)
        else:
            label_image = cv2.imread(os.path.join(use_dir, 'gt_image_2', name + ".png"))
            label = np.zeros((orig_height, orig_width), dtype=np.uint8)
            label[(label_image == [255, 0, 255]).all(axis=2)] = 1

        rgb_image = cv2.resize(rgb_image, self.use_size)
        label = cv2.resize(label, self.use_size, interpolation=cv2.INTER_NEAREST)

        if self.use_surface_normal:
            k = [[7.215377e+02, 0.000000e+00, 6.095593e+02],
                 [0.000000e+00, 7.215377e+02, 1.728540e+02],
                 [0.000000e+00, 0.000000e+00, 1.000000e+00]]
            another_image = get_surface_normals(depth_image.astype(np.float32) / 1000, k)
            another_image = cv2.resize(another_image, self.use_size)
        else:
            another_image = depth_image.astype(np.float32) / 65535
            another_image = cv2.resize(another_image, self.use_size)
            another_image = another_image[:, :, np.newaxis]

        label[label > 0] = 1
        rgb_image = rgb_image.astype(np.float32) / 255

        rgb_image = transforms.ToTensor()(rgb_image)
        another_image = transforms.ToTensor()(another_image)

        label = torch.from_numpy(label)
        label = label.type(torch.LongTensor)

        return {'rgb_image': rgb_image, 'another_image': another_image, 'label': label,
                'path': name, 'orig_size': (orig_width, orig_height)}

    def __len__(self):
        return len(self.image_list)


""" Validation of the modelDescription.xml """

from typing import List

from fmpy.model_description import ModelDescription

def validate_fmu(filename: str) -> List[str]:
    """ Validate the following aspects of an FMU

    modelDescription.xml:
    - validation against the XML schema
    - uniqueness and validity of variable names
    - completeness and integrity of the ModelStructure
    - required start values
    - combinations of causality and variability
    - units

    Parameters:
        filename  filename of the FMU, directory with extracted FMU or file like object

    Returns:
        a list of the problems found
    """

    from . import read_model_description
    from .model_description import ValidationError
    import os
    import zipfile

    problems = []

    # check file paths
    if isinstance(filename, str) and os.path.isfile(filename):
        with zipfile.ZipFile(filename, 'r') as zf:
            for file in zf.filelist:
                if '\\' in file.orig_filename:
                    problems.append(f'The file path "{file.orig_filename}" contains a backslash.')

    try:
        read_model_description(filename,
                               validate=True,
                               validate_variable_names=True,
                               validate_model_structure=True)
    except ValidationError as e:
        problems = e.problems
    except Exception as e:
        problems = [str(e)]

    return problems

def validate_model_description(model_description: ModelDescription, validate_variable_names: bool = False, validate_model_structure: bool = False) -> List[str]:

    problems = []

    if validate_variable_names:
        problems += _validate_variable_names(model_description)

    unit_definitions = {}

    for unit in model_description.unitDefinitions:
        unit_definitions[unit.name] = [display_unit.name for display_unit in unit.displayUnits]

    variable_names = set()

    # assert unique variable names (FMI 1.0 spec, p. 34, FMI 2.0 spec, p. 45)
    for v in model_description.modelVariables:
        if v.name in variable_names:
            problems.append(f'The variable name "{v.name}" (line {v.sourceline}) is not unique.')
        variable_names.add(v.name)

    is_fmi2 = model_description.fmiVersion == '2.0'
    is_fmi3 = model_description.fmiVersion.startswith('3.0')

    # assert legal variability
    for variable in model_description.modelVariables:
        if variable.type not in {'Real', 'Float32', 'Float64'} and variable.variability == 'continuous':
            problems.append(f'The variable "{variable.name}" (line {variable.sourceline}) is of type {variable.type}'
                            f' and must have variability != "continuous".')

    if is_fmi2 or is_fmi3:

        # assert required start values (see FMI 2.0 spec, p. 53)
        for v in model_description.modelVariables:
            if v.type != 'Clock' and (v.initial in {'exact', 'approx'} or v.causality == 'input') and v.start is None:
                problems.append(f'Variable "{v.name}" (line {v.sourceline}) has no start value.')

        # legal combinations of causality, variability, and initial
        legal_combinations = {

            ('structuralParameter', 'fixed', 'exact'),
            ('structuralParameter', 'tunable', 'exact'),

            ('parameter', 'fixed', 'exact'),
            ('parameter', 'tunable', 'exact'),

            ('calculatedParameter', 'fixed', 'calculated'),
            ('calculatedParameter', 'fixed', 'approx'),

            ('calculatedParameter', 'tunable', 'calculated'),
            ('calculatedParameter', 'tunable', 'approx'),

            ('input', 'discrete', 'exact'),
            ('input', 'continuous', 'exact'),

            ('output', 'constant', 'exact'),

            ('output', 'discrete', 'calculated'),
            ('output', 'discrete', 'exact'),
            ('output', 'discrete', 'approx'),

            ('output', 'continuous', 'calculated'),
            ('output', 'continuous', 'exact'),
            ('output', 'continuous', 'approx'),

            ('local', 'constant', 'exact'),

            ('local', 'fixed', 'calculated'),
            ('local', 'fixed', 'approx'),

            ('local', 'tunable', 'calculated'),
            ('local', 'tunable', 'approx'),

            ('local', 'discrete', 'calculated'),
            ('local', 'discrete', 'exact'),
            ('local', 'discrete', 'approx'),

            ('local', 'continuous', 'calculated'),
            ('local', 'continuous', 'exact'),
            ('local', 'continuous', 'approx'),

            ('independent', 'continuous', None),
        }

        for v in model_description.modelVariables:
            if (v.causality, v.variability, v.initial) not in legal_combinations:
                problems.append(f'The combination causality="{v.causality}" and variability="{v.variability}" '
                                f'in variable "{v.name}" (line {v.sourceline}) is not allowed.')

        # check for illegal start values (see FMI 2.0.2 spec, p. 49)
        for v in model_description.modelVariables:

            if v.initial == 'calculated' and v.start:
                problems.append(f'The variable "{v.name}" (line {v.sourceline}) has initial="calculated" but provides a start value.')

            if v.causality in 'independent' and v.start:
                problems.append(f'The variable "{v.name}" (line {v.sourceline}) has causality="independent" but provides a start value.')

        # validate units (see FMI 2.0 spec, p. 33ff.)
        for v in model_description.modelVariables:

            unit = v.unit

            if unit is None and v.declaredType is not None:
                unit = v.declaredType.unit

            if unit is not None and unit not in unit_definitions:
                problems.append(f'The unit "{unit}" of variable "{v.name}" (line {v.sourceline}) is not defined.')

            if v.displayUnit is not None and v.displayUnit not in unit_definitions[unit]:
                problems.append(f'The display unit "{v.displayUnit}" of variable "{v.name}" (line {v.sourceline}) is not defined.')

        if validate_model_structure:
            problems += _validate_model_structure(model_description)

    if is_fmi3:

        # assert independent variable
        if sum(v.causality == 'independent' for v in model_description.modelVariables) != 1:
            problems.append("Exactly one independent variable must be defined.")

        # assert unique value references
        variables = dict()

        for v in model_description.modelVariables:
            if v.valueReference in variables:
                p = variables[v.valueReference]
                problems.append(f'Variable "{v.name}" (line {v.sourceline}) has the same value reference as variable "{p.name}" (line {p.sourceline}).')
            else:
                variables[v.valueReference] = v

    return problems

def _validate_model_structure(model_description: ModelDescription) -> List[str]:

    problems = []

    # validate outputs
    expected_outputs = set(v for v in model_description.modelVariables if v.causality == 'output')
    outputs = set(u.variable for u in model_description.outputs)

    if expected_outputs != outputs:
        problems.append('ModelStructure/Outputs must have exactly one entry for each variable with causality="output".')

    # validate derivatives
    derivatives = set(v for v in model_description.modelVariables if v.derivative is not None)
    for i, state_derivative in enumerate(model_description.derivatives):
        if state_derivative.variable not in derivatives:
            problems.append(f'The variable "{state_derivative.variable.name}" (line {state_derivative.variable.sourceline}) '
                            f'referenced by the continuous state derivative {i + 1} (line {state_derivative.sourceline}) '
                            f'must have the attribute "derivative".')

    # validate initial unknowns
    expected_initial_unknowns = set()

    for variable in model_description.modelVariables:

        if variable.causality == 'output' and variable.initial in {'approx', 'calculated'} and not variable.clocks:
            expected_initial_unknowns.add(variable)

        if variable.causality == 'calculatedParameter':
            expected_initial_unknowns.add(variable)

    try:
        for unknown in model_description.derivatives:
            derivative = unknown.variable
            state = derivative.derivative
            for variable in [state, derivative]:
                if variable.initial in {'approx', 'calculated'}:
                    expected_initial_unknowns.add(variable)

        initial_unknowns = set(v.variable for v in model_description.initialUnknowns)

        if initial_unknowns != expected_initial_unknowns:
            expected = ', '.join(sorted(v.name for v in expected_initial_unknowns))
            actual = ', '.join(sorted(v.name for v in initial_unknowns))
            problem = ("ModelStructure/InitialUnknowns does not contain the expected set of variables."
                       f" Expected {{{ expected }}} but was {{{ actual }}}.")
            problems.append(problem)
    except:
        pass  # this check may fail due to inconsistencies detected above

    return problems

def _validate_variable_names(model_description: ModelDescription) -> List[str]:

    problems = []

    if model_description.variableNamingConvention == 'flat':

        for variable in model_description.modelVariables:

            if u'\u000D' in variable.name:
                problems.append(f'Variable "{variable.name}" (line {variable.sourceline}) contains an illegal carriage return character (U+000D).')

            if u'\u000A' in variable.name:
                problems.append(f'Variable "{variable.name}" (line {variable.sourceline}) contains an illegal line feed character (U+000A).')

            if u'\u0009' in variable.name:
                problems.append(f'Variable "{variable.name}" (line {variable.sourceline}) contains an illegal tab character (U+0009).')

    else:  # variableNamingConvention == structured

        from lark import Lark

        grammar = r"""
            name            : identifier | "der(" identifier ("," unsignedinteger)? ")"
            identifier      : bname arrayindices? ("." bname arrayindices?)*
            bname           : nondigit (nondigit|digit)* | qname
            nondigit        : "_" | "a".."z" | "A".."Z"
            digit           : "0".."9"
            qname           : "'" ( qchar | escape )+ "'"
            qchar           : nondigit | digit | "!" | "#" | "$" | "%" | "&" | "(" | ")"
                              | "*" | "+" | "," | "-" | "." | "/" | ":" | ";" | "<" | ">"
                              | "=" | "?" | "@" | "[" | "]" | "^" | "{" | "}" | "|" | "~" | " "
            escape          : "\'" | "\"" | "\?" | "\\" | "\a" | "\b" | "\f" | "\n" | "\r" | "\t" | "\v"
            arrayindices    : "[" unsignedinteger ("," unsignedinteger)* "]"
            unsignedinteger : digit+
            """

        parser = Lark(grammar, start='name')

        for variable in model_description.modelVariables:
            try:
                parser.parse(variable.name)
            except Exception as e:
                problems.append('"%s" (line %s) is not a legal variable name for naming convention "structured". %s'
                                % (variable.name, variable.sourceline, e))

    return problems


#!/usr/bin/env python3

# std
import collections
from math import pi

# 3rd
import numpy as np
from bokeh.palettes import Reds
from bokeh.plotting import figure
from bokeh.transform import cumsum
import pandas as pd

# ours
from verzettler.zettelkasten import Zettelkasten
from verzettler.bokeh_utils import int_hist, int_hist_from_binned_data

def depth_histogram(zk: Zettelkasten):
    data = zk.get_nnotes_by_depth()
    _ds = list(data.keys())
    xs = np.arange(min(_ds), max(_ds) + 1)
    counts = np.array([data[x] if x in data else 0 for x in xs])
    edges = [i - 0.5 for i in xs]
    edges.append(edges[-1] + 1)
    edges = np.array(edges)
    print(counts)
    print(edges)
    return int_hist_from_binned_data(
        counts, edges, title="Depth", x_axis_label="Depth", x_tooltip="Depth"
    )

def make_link_histogram(zk: Zettelkasten):
    data = [len(note.links) for note in zk.notes]
    bins = [i - 0.5 for i in range(20)]
    plot = int_hist(
        data,
        bins=bins,
        title="Links per note",
        x_axis_label="Links per note",
        x_tooltip="Links per note",
    )

    return plot

def make_backlink_histogram(zk: Zettelkasten):
    backlinks = collections.defaultdict(int)
    for note in zk.notes:
        for link in note.links:
            backlinks[link] += 1
    data = list(backlinks.values())
    bins = [i - 0.5 for i in range(20)]
    plot = int_hist(
        data,
        bins=bins,
        title="Backlinks per note",
        x_axis_label="Backlinks per note",
        x_tooltip="Backlinks per note",
    )

    return plot

def zk_name_pie_chart(zk: Zettelkasten):
    x = collections.defaultdict(int)
    for n in zk.notes:
        x[n.path.resolve().parent.parent.name] += 1
    data = (
        pd.Series(x)
        .reset_index(name="value")
        .rename(columns={"index": "country"})
    )
    print(x)
    data["angle"] = data["value"] / data["value"].sum() * 2 * pi
    # fixme: problems if we have <= 2 zks
    data["color"] = Reds[len(x)]

    p = figure(
        plot_height=350,
        title="Pie Chart",
        toolbar_location=None,
        tools="hover",
        tooltips="@country: @value",
        x_range=(-0.5, 1.0),
        sizing_mode="scale_width",
    )

    p.wedge(
        x=0,
        y=1,
        radius=0.4,
        start_angle=cumsum("angle", include_zero=True),
        end_angle=cumsum("angle"),
        line_color="white",
        fill_color="color",
        legend_field="country",
        source=data,
    )

    p.axis.axis_label = None
    p.axis.visible = False
    p.grid.grid_line_color = None
    return p


import unittest
from models.rectangle import Rectangle
from models.base import Base
from models.square import Square
import os
import json

"""a"""

class TestBase(unittest.TestCase):
    def test_id(self):
        # Test création d'objets avec ID spécifié
        b1 = Base(100)
        self.assertEqual(b1.id, 100)

        b2 = Base(200)
        self.assertEqual(b2.id, 200)

        # Test création d'objets sans ID spécifié
        b3 = Base()
        self.assertEqual(b3.id, 1)

        b4 = Base()
        self.assertEqual(b4.id, 2)

        b5 = Base()
        self.assertEqual(b5.id, 3)

    def test_to_json_string(self):
        r1 = Rectangle(10, 7, 2, 8)
        dictionary = r1.to_dictionary()
        json_str = Base.to_json_string([dictionary])
        self.assertEqual(type(json_str), str)

        empty_json_str = Base.to_json_string([])
        self.assertEqual(empty_json_str, "[]")

        none_json_str = Base.to_json_string(None)
        self.assertEqual(none_json_str, "[]")

    def test_save_to_file(self):
        r1 = Rectangle(10, 7, 2, 8)
        r2 = Rectangle(2, 4)
        Rectangle.save_to_file([r1, r2])

        with open("Rectangle.json", "r") as file:
            json_content = file.read()
            expected_content = json.dumps([r1.to_dictionary(), r2.to_dictionary()])
            self.assertEqual(json_content, expected_content)

        os.remove("Rectangle.json")

    def test_from_json_string(self):
        # Test avec une liste de dictionnaires non vide
        list_input = [
            {'id': 89, 'width': 10, 'height': 4},
            {'id': 7, 'width': 1, 'height': 7}
        ]
        json_list_input = Rectangle.to_json_string(list_input)
        list_output = Rectangle.from_json_string(json_list_input)
        self.assertEqual(list_output, list_input)

    def test_load_from_file(self):
        """ Test load_from_file method """
        r1 = Rectangle(10, 7, 2, 8)
        r2 = Rectangle(2, 4)
        list_rectangles = [r1, r2]
        Rectangle.save_to_file(list_rectangles)
        loaded_rectangles = Rectangle.load_from_file()
        self.assertEqual(len(list_rectangles), len(loaded_rectangles))
        for r in loaded_rectangles:
            self.assertIsInstance(r, Rectangle)

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


from mighty.applications.messenger.backends import MissiveBackend
from mighty.functions import setting
from mighty.apps import MightyConfig
from mighty.applications.messenger import choices
import requests, json

class MissiveBackend(MissiveBackend):
    APIFROM = setting('PAASOO_FROM', 'MIGHTY')
    APIKEY = setting('PAASOO_KEY', False)
    APISECRET = setting('PAASOO_SECRET', False)
    APIURL = "https://api.paasoo.com/json?key=%(key)s&secret=%(secret)s&from=%(from)s&to=%(to)s&text=%(text)s"
    in_error = False

    def get_api_url(self):
        return self.APIURL % {
            "key": self.APIKEY,
            "secret": self.APISECRET,
            "from": self.APIFROM,
            "to": self.missive.target,
            "text": self.missive.txt,
        }

    def valid_response(self, response):
        if response.status_code not in [200, 201]:
            self.missive.trace = str(response.json())
            self.in_error = True
            return False
        return True

    def send_sms(self):
        over_target = setting('MISSIVE_PHONE', False)
        self.missive.target = over_target if over_target else self.missive.target
        self.missive.status = choices.STATUS_SENT
        if setting('MISSIVE_SERVICE', True):
            api_url = self.get_api_url(self.missive)
            headers = {'accept': 'application/json'}
            response = requests.get(self.get_api_url(), headers=headers)
            if self.valid_response(response):
                self.missive.msg_id = response.json()['messageid']
        if not self.in_error:
            self.missive.to_sent()
        self.missive.save()
        return self.missive.status


from itertools import combinations
import sys
input = sys.stdin.readline
N, M = map(int, input().split())
city = [list(map(int, input().split())) for _ in range(N)]

house = []
chicken = []

for i in range(N):
    for j in range(N):
        if city[i][j] == 1:
            house.append((i, j))
        elif city[i][j] == 2:
            chicken.append((i, j))

minV = float('inf')
for ch in combinations(chicken, M):
    sumvV= 0
    for home in house:
        result = []
        for i in ch:
            result.append(abs(home[0] - i[0]) + abs(home[1] - i[1]))
        sumvV += min(result)
        if minV <= sumvV:
            break
    if sumvV < minV:
        minV = sumvV

print(minV)


"""
站点描述
"""
from loguru import logger
from lxml import etree

from network_information_source.common import net_utils

def website_desc(url: str) -> str:
    if not url:
        return ''

    headers = {
    }
    desc = ''
    try:
        r = net_utils.req('GET', url, headers=headers)
        html = etree.HTML(r)
        desc = ''.join(html.xpath("//meta[contains(@name,'description')]/@content"))

    except Exception as ex:
        logger.error(f'{url} 无站点描述信息')

    return desc

if __name__ == '__main__':
    print(website_desc('https://www.sina.com.cn'))


import discord
from discord.ext import commands, pages
from rtadubai import Shail

async def stop_searcher(ctx: discord.AutocompleteContext):
    try:
        return Shail.stopnames(ctx.value)
    except Exception as e:
        print(e)
        return []

class journey_cog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.slash_command()
    @discord.option(name='stop', type=str, description="Stop to check departures", autocomplete=stop_searcher)
    async def departures(self, ctx, stop):
        await ctx.defer()
        try:
            stop = Shail.Stop(name=stop)
            departures = Shail.departures(stop)
        except Exception as e:
            await ctx.respond(e)
            return
        if len(departures) == 0:
            await ctx.respond(f"No departures found for {stop.name}")
        paginator = pages.Paginator(pages=departure_embeds(departures, stop))
        await paginator.respond(ctx.interaction)

    @commands.slash_command()
    @discord.option(name='fromstop', type=str, description="From stop", autocomplete=stop_searcher)
    @discord.option(name='tostop', type=str, description="To stop", autocomplete=stop_searcher)
    async def journey(self, ctx, fromstop, tostop):
        await ctx.defer()
        try:
            fromstop = Shail.Stop(name=fromstop)
            tostop = Shail.Stop(name=tostop)
            journey = Shail.journey_planner(fromstop, tostop)
        except Exception as e:
            await ctx.respond(e)
            return
        paginator = pages.Paginator(pages=journey_embeds(journey), show_menu=True, menu_placeholder="Select a Journey")
        await paginator.respond(ctx.interaction)

    @commands.Cog.listener()
    async def on_application_command_error(self, error):
        if isinstance(error, discord.errors.NotFound):
            pass
        else:
            raise error

def departure_embeds(departures, stop):
    embeds = []
    for departure in departures:
        embed = discord.Embed(title=f"{stop.name}", description=f"Departures at {stop.name}")
        embed.add_field(name="Mode", value=departure["mode"], inline=False)
        embed.add_field(name="Type", value=departure["type"], inline=False)
        embed.add_field(name="Direction", value=departure["direction"], inline=False)
        embed.add_field(name="Scheduled Time", value=departure["scheduled_time"], inline=False)
        embed.add_field(name="Estimated Time", value=departure["estimated_time"], inline=False)
        embed.add_field(name="Status", value=departure["status"], inline=False)
        embeds.append(embed)
    return embeds

def journey_embeds(journeys):
    menus = []
    for journey in journeys:
        embeds = []
        embed = discord.Embed()
        embed.title = "Journey Planner"
        embed.add_field(name="Staring From", value=journey["startstop"], inline=False)
        embed.add_field(name="Destination", value=journey["endstop"], inline=False)
        embed.add_field(name="Starting Time", value=journey["starttime"], inline=False)
        embed.add_field(name="Ending Time", value=journey["endtime"], inline=False)
        embed.add_field(name="Duration", value=journey["duration"], inline=False)
        embed.add_field(name="Amount", value=journey["amount"], inline=False)
        embeds.append(embed)
        for i in journey['journeys']:
            embed = discord.Embed()
            embed.add_field(name="Starting Time", value=i["starttime"], inline=False)
            embed.add_field(name="Ending Time", value=i["endtime"], inline=False)
            embed.add_field(name="From", value=i["from"], inline=False)
            embed.add_field(name="To", value=i["to"], inline=False)
            embed.add_field(name="Method", value=i["method"], inline=False)
            embed.add_field(name="Mode", value=i["mode"], inline=False)
            embed.add_field(name="Duration", value=i["duration"], inline=False)
            embeds.append(embed)
        menus.append(
            pages.PageGroup(
                pages=embeds,
                label=f"Starting time : {journey['starttime']}, Ending Time: {journey['endtime']}",
                description=f"Duration: {journey['duration']}, Amount: {journey['amount']}",
            )
        )
    return menus

def setup(bot):
    bot.add_cog(journey_cog(bot))
    print("Journey cog loaded")


from django.urls import path, reverse_lazy
from . import views

app_name='adverts'
urlpatterns = [
    path('', views.AdvertListView.as_view(), name='all'),
    path('advert/<int:pk>', views.AdvertDetailView.as_view(), name='advert_detail'),
    path('advert/create', views.AdvertCreateView.as_view(success_url=reverse_lazy('adverts:all')), name='advert_create'),
    path('advert/<int:pk>/update', views.AdvertUpdateView.as_view(success_url=reverse_lazy('adverts:all')), name='advert_update'),
    path('advert/<int:pk>/delete', views.AdvertDeleteView.as_view(success_url=reverse_lazy('adverts:all')), name='advert_delete'),
    path('advert_picture/<int:pk>', views.stream_file, name='advert_picture'),
    path('advert/<int:pk>/comment', views.CommentCreateView.as_view(), name='advert_comment_create'),
    path('comment/<int:pk>/delete', views.CommentDeleteView.as_view(success_url=reverse_lazy('adverts:all')), name='advert_comment_delete'),
    path('advert/<int:pk>/favorite', views.AddFavoriteView.as_view(), name='advert_favorite'),
    path('advert/<int:pk>/unfavorite', views.DeleteFavoriteView.as_view(), name='advert_unfavorite'),
]

# We use reverse_lazy in urls.py to delay looking up the view until all the paths are defined


from .interfaces import IFormatterFactory
from zope.interface import provider

import bbcode
import re

class copy_snippet(object):
    def __init__(self, snippet):
        self.__bbcode_copy_snippet__ = snippet

    def __call__(self, func):
        func.__bbcode_copy_snippet__ = self.__bbcode_copy_snippet__
        return func

class template_snippet(object):
    def __init__(self, snippet):
        self.__bbcode_template_snippet__ = snippet

    def __call__(self, func):
        func.__bbcode_template_snippet__ = self.__bbcode_template_snippet__
        return func

# parts of this code are inspired by and partly taken from
# https://github.com/dcwatson/bbcode/blob/master/bbcode.py

# b 	[b]test[/b] 	test
# i 	[i]test[/i] 	test
# u 	[u]test[/u] 	test
# s 	[s]test[/s] 	test
# hr 	[hr]

# br 	[br]

# sub 	x[sub]3[/sub] 	x3
# sup 	x[sup]3[/sup] 	x3
# list/* 	[list][*] item[/list]

item

# quote 	[quote]hello[/quote]
hello

# code 	[code]x = 3[/code] 	x = 3
# center 	[center]hello[/center]
hello

# color 	[color=red]red[/color] 	red
# url 	[url=www.apple.com]Apple[/url] 	Apple

TEMPLATES = {
    "url": '{text}',
}

def make_simple_formatter(tag_name, format_string, **kwargs):
    """
    Creates a formatter that takes the tag options dictionary, puts a value key
    in it, and uses it as a format dictionary to the given format string.
    """

    def _render(name, value, options, parent, context):
        fmt = {}
        if options:
            fmt.update(options)
        fmt.update({"value": value})
        return format_string % fmt

    return _render

@provider(IFormatterFactory)
@copy_snippet("[b][/b]")
@template_snippet("[b]$TEXT[/b]$CURSOR")
def b_factory():
    """Bold or strong text:
A [b]bold[/b] text.

    Example:

    A [b]bold[/b] text.
    """
    return make_simple_formatter("b", "%(value)s"), {}

@provider(IFormatterFactory)
@copy_snippet("[i][/i]")
@template_snippet("[i]$TEXT[/i]$CURSOR")
def i_factory():
    """Italic or emphasised text:
An [i]italic/emphasised[/i] text.

    Example:

    An [i]italic/emphasised[/i] text.
    """
    return make_simple_formatter("i", "%(value)s"), {}

@provider(IFormatterFactory)
@copy_snippet("[u][/u]")
@template_snippet("[u]$TEXT[/u]$CURSOR")
def u_factory():
    """Underlined or unarticulated text:
An [u]underlined[u] text.

    Example:

    An [u]underlined[/u] text.
    """
    return make_simple_formatter("u", "%(value)s"), {}

@provider(IFormatterFactory)
@copy_snippet("[s][/s]")
@template_snippet("[s]$TEXT[/s]$CURSOR")
def s_factory():
    """Strike through or deleted text: [s]test[/s]"""
    return make_simple_formatter("s", "%(value)s"), {}

@provider(IFormatterFactory)
@copy_snippet("[sub][/sub]")
@template_snippet("[sub]$TEXT[/sub]$CURSOR")
def sub_factory():
    """Subscript text:
H[sub]2[/sub]O

    Example:

    H[sub]2[/sub]O
    """
    return make_simple_formatter("sub", "%(value)s"), {}

@provider(IFormatterFactory)
@copy_snippet("[sup][/sup]")
@template_snippet("[sup]$TEXT[/sup]$CURSOR")
def sup_factory():
    """Superscript text:
r[sup]2[/sup]

    Example:

    r[sup]2[/sup]
    """
    return make_simple_formatter("sup", "%(value)s"), {}

@provider(IFormatterFactory)
@copy_snippet("[hr]")
@template_snippet("$TEXT[hr]$CURSOR")
def hr_factory():
    """Horizontal ruler:
Above ruler[hr]Below ruler

    Example:

    Above ruler[hr]Below ruler
    """
    return make_simple_formatter("hr", "
"), {"standalone": True}

@provider(IFormatterFactory)
@copy_snippet("[br]")
@template_snippet("$TEXT[br]$CURSOR")
def br_factory():
    """Line break in text:
A line[br]break in the text.

    Example:

    A line[br]break in the text.
    """
    return make_simple_formatter("br", "
"), {"standalone": True}

@provider(IFormatterFactory)
@copy_snippet(
    """\
[list]
    [*] item
[/list]
"""
)
@template_snippet(
    """\
[list]
    [*] $TEXT
    [*] $CURSOR
[/list]
"""
)
def list_factory():
    """List with bullets or numbers. Use '*' for bullet points or for numbers one out of '1', '01, 'a', 'A', 'i' or 'I'.
    Bullet points: [list][*] item[/list]
    Numbered: [list][1] item[/list]
    """

    def _render_list(name, value, options, parent, context):
        list_type = options["list"] if (options and "list" in options) else "*"
        css_opts = {
            "1": "decimal",
            "01": "decimal-leading-zero",
            "a": "lower-alpha",
            "A": "upper-alpha",
            "i": "lower-roman",
            "I": "upper-roman",
        }
        tag = "ol" if list_type in css_opts else "ul"
        css = (
            ' style="list-style-type:%s;"' % css_opts[list_type]
            if list_type in css_opts
            else ""
        )
        return "<%s%s>%s</%s>" % (tag, css, value, tag)

    return _render_list, {
        "transform_newlines": False,
        "strip": True,
        "swallow_trailing_newline": True,
    }

@provider(IFormatterFactory)
def list_item_factory():
    # no doc string, so will not appear in documentation, helper for list
    def _render_list_item(name, value, options, parent, context):
        if not parent or parent.tag_name != "list":
            return "[*]%s
" % value

        return "
%s
" % value

    return _render_list_item, {
        "newline_closes": True,
        "transform_newlines": False,
        "same_tag_closes": True,
        "strip": True,
        "level": 1,
    }

@provider(IFormatterFactory)
@copy_snippet("[quote][/quote]")
@template_snippet("[quote]$TEXT[/quote]$CURSOR")
def quote_factory():
    return make_simple_formatter("quote", "
%(value)s
"), {
        "strip": True,
        "swallow_trailing_newline": True,
    }

@provider(IFormatterFactory)
@copy_snippet("[code][/code]")
@template_snippet("[code]$TEXT[/code]$CURSOR")
def code_factory():
    """Code text:
Some random Code: [code]print("Hello World")[/code]

    Example:

    Some random Code: [code]print("Hello World")[/code]
    """

    return make_simple_formatter("code", "%(value)s"), {
        "render_embedded": False,
        "transform_newlines": False,
        "swallow_trailing_newline": True,
        "replace_cosmetic": False,
    }

@provider(IFormatterFactory)
@copy_snippet("[color=red][/color]")
@template_snippet("[color=$CURSOR]$TEXT[/color]")
def color_factory():
    def _render_color(name, value, options, parent, context):
        if "color" in options:
            color = options["color"].strip()
        elif options:
            color = list(options.keys())[0].strip()
        else:
            return value
        match = re.match(r"^([a-z]+)|^(#[a-f0-9]{3,6})", color, re.I)
        color = match.group() if match else "inherit"
        return '%(value)s' % {
            "color": color,
            "value": value,
        }

    return _render_color(), {}

@provider(IFormatterFactory)
@copy_snippet("[center][/center]")
@template_snippet("[center]$TEXT[/center]$CURSOR")
def center_factory():
    """Centered text:
[center]centered text[/center]

    Example:

    [center]centered text[/center]
    """
    return (
        make_simple_formatter(
            "center", '
%(value)s
'
        ),
        {},
    )

@provider(IFormatterFactory)
@copy_snippet("[url=https://plone.org]Plone[/url]")
@template_snippet("[url=$CURSOR]$TEXT[/url]")
def url_factory():
    """A hyper link in the text:
Welcome to [url=www.plone.org]Plone[/url]!

    Example:

    Welcome to [url=www.plone.org]Plone[/url]!
    """

    def _render_url(name, value, options, parent, context):
        if options and "url" in options:
            href = options["url"]
            # Option values are not escaped for HTML output.
            for find, repl in bbcode.Parser.REPLACE_ESCAPE:
                value = value.replace(find, repl)
        else:
            href = value
        # Completely ignore javascript: and data: "links".
        if re.sub(r"[^a-z0-9+]", "", href.lower().split(":", 1)[0]) in (
            "javascript",
            "data",
            "vbscript",
        ):
            return ""
        # Only add the missing https:// if it looks like it starts with a domain name.
        if "://" not in href and bbcode._domain_re.match(href):
            href = "https://" + href
        return TEMPLATES["url"].format(href=href.replace('"', "%22"), text=value)

    return _render_url, {"replace_links": False, "replace_cosmetic": False}


from collections import defaultdict

def solution(userIds, report, k):
    deduplicateReport = set(report)

    reportResult = getReportResult(deduplicateReport)
    sendMailCounts = getSendMailCounts(reportResult)

    return [sendMailCounts[userId] for userId in userIds]

def getReportResult(report):
    reportResult = defaultdict(list)

    for r in report:
        reportingUserId, reportedUserId = r.split(' ')
        reportResult[reportedUserId].append(reportingUserId)

    return reportResult

def getSendMailCounts(reportResult, k):
    sendMailCounts = defaultdict(int)

    for reportingUsers in reportResult.values():
        reportCount = len(reportingUsers)

        if reportCount < k:
            break

        for reportingUser in reportingUsers:
            sendMailCounts[reportingUser] += 1

    return sendMailCounts


#! python
from pygame.sprite import Sprite
import pygame

class Planet(Sprite):
    def __init__(self):
        # Call the parent class (Sprite) constructor
        super(Planet, self).__init__()
        self.surface = pygame.image.load("../images/surface.png").convert()
        self.rect = None

    def render(self):
        self.image = pygame.Surface([800, 100]).convert()
        self.image.blit (self.surface, (0, 0), (0, 0, 800, 100))
        self.image.set_colorkey((255, 255, 255))
        self.rect = self.image.get_rect()
        self.rect.x = 0
        self.rect.y = 500
        self.mask = pygame.mask.from_surface(self.image)


import time
import csv
from selenium import webdriver
import threading
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By

types=["birth","marriage","death"]
try:
    years = []

    while True:
        years.append(int(input("enter a year:")))
        print("enter empty line to start the program")
except:
    print(years)
months=[1,2,3,4,5,6,7,8,9,10,11,12]
states = [
"Acre",
"Alagoas",
"Amazonas",
"Amapá",
"Bahia",
"Ceará",
"Distrito Federal",
"Espírito Santo",
"Goiás",
"Maranhão",
"Minas Gerais",
"Mato Grosso do Sul",
"Mato Grosso",
"Pará",
"Paraíba",
"Pernambuco",
"Piauí",
"Paraná",
"Rio de Janeiro",
"Rio Grande do Norte",
"Rondônia",
"Roraima",
"Rio Grande do Sul",
"Santa Catarina",
"Sergipe",
"São Paulo",
"Tocantins",
]
csvfile = open('records.csv', 'w', encoding='utf8', newline='')
fnames = ['Tipo_Registro', 'Ano','Mes','Estado','Cidade','Qnt_Registros']
writer = csv.DictWriter(csvfile, fieldnames=fnames)
print("this will take time please wait...")
def work(year):
    csvfile = open('records'+str(year)+'.csv', 'w', encoding='utf8', newline='')
    fnames = ['Tipo_Registro', 'Ano', 'Mes', 'Estado', 'Cidade', 'Qnt_Registros']
    writer = csv.DictWriter(csvfile, fieldnames=fnames)
    driver = webdriver.Firefox()
    driver.get("https://transparencia.registrocivil.org.br/registros")
    for type in types:
        for month in months:
            for state in states:
                driver.find_element_by_xpath('//div[input[@value="'+type+'"]]').click()
                driver.find_element_by_xpath('//fieldset[@id="datePickrGroup"]/div').click()
                WebDriverWait(driver, 20).until(
                    EC.element_to_be_clickable(
                        (By.XPATH, '//span[text()="'+str(year)+'"]')))
                driver.find_element_by_xpath('//span[text()="'+str(year)+'"]').click()
                driver.find_element_by_xpath('//fieldset[@id="__BVID__62"]/div').click()
                monthlist = driver.find_elements_by_xpath('//fieldset[@id="__BVID__62"]/div//ul/li/span/span')
                monthlist[month].click()

                driver.find_element_by_xpath('//div[@id="__BVID__70"]/div').click()
                WebDriverWait(driver, 20).until(
                    EC.element_to_be_clickable((By.XPATH, '//div[@id="__BVID__70"]/div//ul/li/span/span[text()="'+state+'"]')))

                driver.find_element_by_xpath('//div[@id="__BVID__70"]/div//ul/li/span/span[text()="'+state+'"]').click()

                try:
                    WebDriverWait(driver, 20).until(
                        EC.element_to_be_clickable((By.XPATH, '//button[@class="btn btn-success"]')))
                    driver.find_element_by_xpath('//button[@class="btn btn-success"]').click()
                except:
                    driver.find_element_by_xpath('//button[@class="btn btn-success"]').click()
                next = True
                while next:
                    WebDriverWait(driver, 60).until(EC.presence_of_element_located(
                        (By.XPATH, '//tbody/tr')))
                    rows = driver.find_elements_by_xpath('//tbody/tr')
                    for row in rows:
                        if type == "birth":
                            tipo = "Nascimentos"
                        if type == "marriage":
                            tipo = "Casamentos"
                        if type == "death":
                            tipo = "Óbitos"
                        city = row.find_elements_by_tag_name("td")[0].text
                        number =row.find_elements_by_tag_name("td")[1].text
                        writer.writerow({'Tipo_Registro': tipo, 'Ano': str(year),'Mes':str(month),'Estado':state,'Cidade':city,'Qnt_Registros':str(number)})
                    try:
                        driver.find_element_by_xpath('//ul[@role="menubar"]/li[last()-1]/button').click()
                    except:
                        next=False
    print(str(year)+" finish" )
threads=[]
for year in years:
    x = threading.Thread(target=work, args=(year,))
    threads.append(x)
for x in threads:
    x.start()

for x in threads:
    x.join()
print("finish")

#driver.find_element_by_xpath('//div[input[@value="birth"]]').click()

#driver.find_element_by_xpath('//fieldset[@id="datePickrGroup"]/div').click()
#//span[text()="2018"]

#driver.find_element_by_xpath('//fieldset[@id="__BVID__62"]/div').click()
#months = driver.find_elements_by_xpath('//fieldset[@id="__BVID__62"]/div//ul/li/span/span')
#months[5].click()

#driver.find_element_by_xpath('//div[@id="__BVID__70"]/div').click()
#//div[@id="__BVID__70"]/div//ul/li/span/span[text()="Rio de Janeiro"]

#//tbody/tr

#//button[@class="btn btn-success"]

#driver.find_element_by_xpath('//ul[@role="menubar"]/li[last()-1]/button').click()


from flask import Flask
app = Flask(__name__)

from flask import request

lightStates = {}
nLights = 5

for i in range(nLights):
    lightStates[i] = False

temp = 0.0
nPeople = 0
luminosity = 0.0

@app.route('/getDeviceStatuses')
def getDeviceStatuses():
    global lightStates
    return str(lightStates)

@app.route('/getDeviceStatus')
def getDeviceStatus():
    global lightStates
    try:
        return str(lightStates[int(request.args.get('deviceId'))])
    except:
        return "False"

@app.route('/setDeviceStatus')
def setDeviceStatus():
    global lightStates
    try:
        lightStates[int(request.args.get('deviceId'))] = ( request.args.get('state') == 'True')
        return "True"
    except:
        return "False"

@app.route('/setTemperature')
def setTemperature():
    global temp
    try:
        temp = float(request.args.get('val'))
        return "True"
    except:
        return "False"

@app.route('/getTemperature')
def getTemperature():
    global temp
    return str(temp)

@app.route('/setLuminosity')
def setLuminosity():
    global luminosity
    try:
        luminosity = float(request.args.get('val'))
        return "True"
    except:
        return "False"

@app.route('/getLuminosity')
def getLuminosity():
    global luminosity
    return str(luminosity)

@app.route('/setPopulation')
def setPopulation():
    global nPeople
    try:
        nPeople = int(request.args.get('val'))
        return "True"
    except:
        return "False"

@app.route('/getPopulation')
def getPopulation():
    global nPeople
    return str(nPeople)

@app.after_request
def apply_caching(response):
    response.headers["Access-Control-Allow-Origin"] = "*"
    return response

# @app.route('/user/<username>')
# def show_user_profile(username):
#     # show the user profile for that user
#     return 'ohho hi  %s' % username

# @app.route('/post/<int:post_id>')
# def show_post(post_id):
#     # show the post with the given id, the id is an integer
#     return 'ohho post %d' % post_id

# @app.route('/both', methods=['GET', 'POST'])
# def login():
#     if request.method == 'POST':
#         print "ohho POST"
#     else:
#         print "ohho GET"

if __name__ == '__main__':
    app.debug = True
    app.run(host= '0.0.0.0')


import asyncapi
from saga_framework.asyncapi_utils import \
    message_to_channel, fake_asyncapi_servers, \
    asyncapi_components_from_asyncapi_channels

from restaurant_service.app_common.messaging import restaurant_service_messaging
from restaurant_service.app_common.messaging.restaurant_service_messaging import \
    create_ticket_message, reject_ticket_message, approve_ticket_message

"""
IMPORTANT!
We do NOT document error responses such as `restaurant_service.create_ticket.response.failure`
We assume that they have standard format (see SagaErrorPayload dataclass)
"""
channels = dict([
    message_to_channel(create_ticket_message.message,
                       create_ticket_message.success_response),
    message_to_channel(reject_ticket_message.message),  # compensation step has no resppnse
    message_to_channel(approve_ticket_message.message,
                       approve_ticket_message.success_response),
])

spec = asyncapi.Specification(
    info=asyncapi.Info(
        title='Restaurant service', version='1.0.0',
        description=f'Takes command messages from "{restaurant_service_messaging.COMMANDS_QUEUE}" queue',
    ),
    channels=channels,
    components=asyncapi_components_from_asyncapi_channels(channels.values()),
    servers=fake_asyncapi_servers,
)

if __name__ == '__main__':
    import yaml
    from asyncapi.docs import spec_asjson

    print(yaml.dump(spec_asjson(spec)))