# Time:  O(n + p)
# Space: O(p)
# Given two sentences words1, words2 (each represented as an array of strings),
# and a list of similar word pairs pairs, determine if two sentences are similar.
#
# For example, "great acting skills" and "fine drama talent" are similar,
# if the similar word pairs are pairs = [["great", "fine"], ["acting","drama"], ["skills","talent"]].
#
# Note that the similarity relation is not transitive.
# For example, if "great" and "fine" are similar, and "fine" and "good" are similar,
# "great" and "good" are not necessarily similar.
#
# However, similarity is symmetric.
# For example, "great" and "fine" being similar is the same as "fine" and "great" being similar.
#
# Also, a word is always similar with itself.
# For example, the sentences words1 = ["great"], words2 = ["great"], pairs = [] are similar,
# even though there are no specified similar word pairs.
#
# Finally, sentences can only be similar if they have the same number of words.
# So a sentence like words1 = ["great"] can never be similar to words2 = ["doubleplus","good"].
#
# Note:
# - The length of words1 and words2 will not exceed 1000.
# - The length of pairs will not exceed 2000.
# - The length of each pairs[i] will be 2.
# - The length of each words[i] and pairs[i][j] will be in the range [1, 20].

# V0
# https://zxi.mytechroad.com/blog/hashtable/leetcode-734-sentence-similarity/
import collections
class Solution(object):
    def areSentencesSimilar(self, words1, words2, pairs):
        if len(words1) != len(words2): return False
        similars = collections.defaultdict(set)
        for w1, w2 in pairs:
            similars[w1].add(w2)
            similars[w2].add(w1)
        for w1, w2 in zip(words1, words2):
            if w1 != w2 and w2 not in similars[w1]:
                return False
        return True

# V0'
import collections
class Solution(object):
    def areSentencesSimilar(self, words1, words2, pairs):
        if len(words1) != len(words2):
            return False
        map_ = collections.defaultdict(set)
        # build the grpah
        for i, j in pairs:
            map_[i].add(j)
            map_[j].add(i)
        for w1, w2 in zip(words1, words2):
            if w1 != w2 and w1 not in map_[w2]:
                return False
        return True

# V1
# http://bookshadow.com/weblog/2017/11/26/leetcode-sentence-similarity/
# https://blog.csdn.net/danspace1/article/details/88942077
# IDEA : ollections.defaultdict(set) --> set IS "ADDABLE"
# IDEA :
# IF len(words1) != len(words2) -> return False
# HAVE A MAPPING RELATIONSHIP (similars) ON PAIRS :
# e.g.
# if pairs = [["great", "fine"], ["acting","drama"], ["skills","talent"]]
# ->
# similars = collections.defaultdict(set)
# for w1, w2 in pairs:
#     similars[w1].add(w2)
#     similars[w2].add(w1)
# -> similars =
# defaultdict(set,
#             {'acting': {'drama'},
#              'drama': {'acting'},
#              'fine': {'great'},
#              'great': {'fine'},
#              'skills': {'talent'},
#              'talent': {'skills'}})
# THEN COMPARE THROUGH words1, words2 WITH similars PATTERN
# RETURN FALSE IF ANY ELEMENT IN words1 !=  words2 AND ELEMENT NOT IN similars RELATIONSHIP
import collections
class Solution(object):
    def areSentencesSimilar(self, words1, words2, pairs):
        """
        :type words1: List[str]
        :type words2: List[str]
        :type pairs: List[List[str]]
        :rtype: bool
        """
        if len(words1) != len(words2): return False
        similars = collections.defaultdict(set)
        for w1, w2 in pairs:
            similars[w1].add(w2)
            similars[w2].add(w1)
        for w1, w2 in zip(words1, words2):
            if w1 != w2 and w2 not in similars[w1]:
                return False
        return True

# V1'
# https://zxi.mytechroad.com/blog/hashtable/leetcode-734-sentence-similarity/
class Solution:
    def areSentencesSimilar(self, words1, words2, pairs):
        if len(words1) != len(words2): return False

        similar_words = {}

        for w1, w2 in pairs:
            if not w1 in similar_words: similar_words[w1] = set()
            if not w2 in similar_words: similar_words[w2] = set()
            similar_words[w1].add(w2)
            similar_words[w2].add(w1)

        for w1, w2 in zip(words1, words2):
            if w1 == w2: continue
            if w1 not in similar_words: return False
            if w2 not in similar_words[w1]: return False
        return True

# V1''
# https://www.jiuzhang.com/solution/sentence-similarity/#tag-highlight-lang-python
class Solution:
    """
    @param words1: a list of string
    @param words2: a list of string
    @param pairs: a list of string pairs
    @return: return a boolean, denote whether two sentences are similar or not
    """
    def isSentenceSimilarity(self, words1, words2, pairs):
        # write your code here
        if(not (len(words1) == len(words2))):
            return False
        mp = {}
        for i in range(len(pairs)):
            S = set()
            if(not (mp.get(pairs[i][0]) == None)):
                S = mp[pairs[i][0]]
            S.add(pairs[i][1])
            mp[pairs[i][0]] = S
        for i in range(len(words1)):
            if(words1[i] == words2[i]):
                continue
            if((mp.get(words1[i]) == None or words2[i] not in mp[words1[i]]) and (mp.get(words2[i]) == None or words1[i] not in mp[words2[i]])):
                return False
        return True

# V2
import collections
class Solution(object):
    def areSentencesSimilar(self, words1, words2, pairs):
        """
        :type words1: List[str]
        :type words2: List[str]
        :type pairs: List[List[str]]
        :rtype: bool
        """
        if len(words1) != len(words2): return False
        similars = collections.defaultdict(set)
        for w1, w2 in pairs:
            similars[w1].add(w2)
            similars[w2].add(w1)
        for w1, w2 in zip(words1, words2):
            if w1 != w2 and w2 not in similars[w1]:
                return False
        return True

# V3
import itertools
class Solution(object):
    def areSentencesSimilar(self, words1, words2, pairs):
        """
        :type words1: List[str]
        :type words2: List[str]
        :type pairs: List[List[str]]
        :rtype: bool
        """
        if len(words1) != len(words2): return False
        lookup = set(map(tuple, pairs))
        return all(w1 == w2 or (w1, w2) in lookup or (w2, w1) in lookup \
                   for w1, w2 in zip(words1, words2))


# -*- coding: utf-8 -*-
import pandas as pd
import numpy as np
import h5py
from pkg_resources import resource_filename

#%%
def _load_dataset(filename, partition='complete', data_type='pandas', **kwargs):
    """
    Load an example dataset from deepsurvk.datasets.
    All datasets correspond to the ones used originally in [#katzman0]_.

    Parameters
    ----------
    filename: string
        Name of the dataset (e.g., 'whas.h5')

    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#katzman0] Katzman, Jared L., et al. "DeepSurv: personalized treatment recommender system using a Cox proportional hazards deep neural network." BMC medical research methodology 18.1 (2018): 24.
    """

    filename_ = resource_filename('deepsurvk', 'datasets/data/' + filename)

    # Read training data.
    with h5py.File(filename_, 'r') as f:
        X_train = f['train']['x'][()]
        E_train = f['train']['e'][()]
        Y_train = f['train']['t'][()].reshape(-1, 1)

    # Read testing data.
    with h5py.File(filename_, 'r') as f:
        X_test = f['test']['x'][()]
        E_test = f['test']['e'][()]
        Y_test = f['test']['t'][()].reshape(-1, 1)

    # Define data partitions.
    if partition == 'training' or partition == 'train':
        X = X_train
        Y = Y_train
        E = E_train
    elif partition == 'testing' or partition == 'test':
        X = X_test
        Y = Y_test
        E = E_test
    elif partition == 'complete':
        X = np.concatenate((X_train, X_test), axis=0)
        Y = np.concatenate((Y_train, Y_test), axis=0)
        E = np.concatenate((E_train, E_test), axis=0)
    else:
        raise ValueError('Invalid partition.')

    # If NumPy, do nothing (already in that format).
    if (data_type == 'numpy') or (data_type=='np') or (data_type=='array'):
        pass

    # Otherwise, convert to pandas DataFrame.
    elif (data_type == 'pandas') or (data_type=='pd') or (data_type=='dataframe') or (data_type=='df'):
        X, Y, E = _numpy_to_pandas(X, Y, E, filename)

    else:
        raise ValueError("Invalid data type.")

    return X, Y, E

#%%
def _numpy_to_pandas(X, Y, E, filename):
    """
    Convert a data NumPy array to pandas DataFrame.

    Parameters
    ----------
    X: NumPy array
        Feature matrix
    Y: NumPy array
        Output array
    E: NumPy array
        Event array
    filename: string
        Name of the dataset (e.g., 'whas.h5')

    Returns
    -------
    tuple
        Tuple with df_X, df_Y, and df_E
    """
    # Get columns names and data types.
    column_names = _get_column_names(filename)
    data_types = _get_data_types(filename)

    # Create pandas DataFrames
    df_X = pd.DataFrame(data=X, columns=column_names)
    df_X = df_X.astype(data_types)

    df_Y = pd.DataFrame(data=Y, columns=['T'], dtype=np.float64)
    df_E = pd.DataFrame(data=E, columns=['E'], dtype=np.int32)

    return df_X, df_Y, df_E

#%%
def _get_column_names(filename):
    """
    Get the data column names (needed to create a pandas DataFrame).

    Parameters
    ----------
    filename: string
        Name of the dataset (e.g., 'whas.h5')

    Returns
    -------
    column_names: list
        Column names corresponding to the data.
    """
    # Remove file name extension.
    filename = filename.split('.h5')[0]

    # Define column names for each dataset.
    if filename=='metabric':
        column_names = ['gene1', 'gene2', 'gene3', 'gene4', 'radio', 'horm', 'chemo', 'er_status', 'age']
    elif filename=='rgbsg':
        column_names = ['horm_treatment', 'grade', 'menopause' ,'age' ,'n_positive_nodes', 'progesterone' ,'estrogen']
    elif filename=='simulated_gaussian':
        column_names = ['x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10']
    elif filename=='simulated_linear':
        column_names = ['x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10']
    elif filename=='simulated_treatment':
        column_names = ['x1', 'x2', 'x3', 'x4', 'x5', 'x6', 'x7', 'x8', 'x9', 'x10', 'treatment']
    elif filename=='support':
        column_names = ['age', 'sex', 'race', 'n_comorbidities', 'diabetes', 'dementia', 'cancer', 'blood_pressure', 'heart_rate', 'respiration_rate', 'temperature', 'white_blood_cell', 'serum_sodium', 'serum_creatinine']
    elif filename=='whas':
        column_names = ['shock', 'age', 'sex', 'bmi', 'chf', 'recurrent']

    return column_names

#%%
def _get_data_types(filename):
    """
    Get the right data types of the columns (needed to create a pandas DataFrame).

    Parameters
    ----------
    filename: string
        Name of the dataset (e.g., 'whas.h5')

    Returns
    -------
    data_types: dictionary
        Each key corresponds to the column name.
        Each value corresponds to the data type.
    """
    # Remove file name extension.
    filename = filename.split('.h5')[0]

    # Assign data type for each column for each dataset.
    if filename=='metabric':
        data_types_ = ['float64', 'float64', 'float64', 'float64', 'int32', 'int32', 'int32', 'int32', 'float64']
    elif filename=='rgbsg':
        data_types_ = ['int32', 'int32', 'int32', 'int32' ,'int32', 'int32', 'int32']
    elif filename=='simulated_gaussian':
        data_types_ = ['float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64']
    elif filename=='simulated_linear':
        data_types_ = ['float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64']
    elif filename=='simulated_treatment':
        data_types_ = ['float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'float64', 'int32']
    elif filename=='support':
        data_types_ = ['float64', 'int32', 'int32', 'int32', 'int32', 'int32', 'int32', 'int32', 'int32', 'int32', 'float64', 'int32', 'float64', 'float64']
    elif filename=='whas':
        data_types_ = ['int32', 'int32', 'int32', 'float64', 'int32', 'int32']

    # Create dictionary.
    keys = _get_column_names(filename)
    data_types = dict(zip(keys, data_types_))

    return data_types

#%%
def load_metabric(partition='complete', **kwargs):
    """
    Data from the Molecular Taxonomy of Breast Cancer International
    Consortium (METABRIC), which uses gene and protein expression
    profiles to determine new breast cancer subgroups

    It consists of clinical features of 1980 patients, of which 57.72%
    have an observed death due to breast cancer with a median survival time
    of 116 months. However, the file only contains data of 1904 patients.

    For more information, see [#curtis]_ as well as the accompanying README.

    Parameters
    ----------
    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#curtis] Curtis, Christina, et al. "The genomic and transcriptomic architecture of 2,000 breast tumours reveals novel subgroups." Nature 486.7403 (2012): 346-352.
    """
    return _load_dataset('metabric.h5', partition=partition, **kwargs)

#%%
def load_rgbsg(partition='complete', **kwargs):
    """
    The training partition belongs to the Rotterdam tumor bank dataset [#foekens]_.
    It contains records of 1546 patients with node-positive breast cancer.
    Nearly 90% of the patients have an observed death time.

    The testing partitiong belongs to the German Breast Cancer Study
    Group (GBSG) [#schumacher]_. It contains records for 686 patients (of which 56 % are
    censored) in a randomized clinical trial that studied the effects of
    chemotherapy and hormone treatment on survival rate.

    For more information, see [#foekens]_ and [#schumacher]_, as well as the accompanying README.

    Parameters
    ----------
    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#foekens] Foekens, John A., et al. "The urokinase system of plasminogen activation and prognosis in 2780 breast cancer patients." Cancer research 60.3 (2000): 636-643.

    .. [#schumacher] Schumacher, M., et al. "Randomized 2 x 2 trial evaluating hormonal treatment and the duration of chemotherapy in node-positive breast cancer patients. German Breast Cancer Study Group." Journal of Clinical Oncology 12.10 (1994): 2086-2093.
    """
    return _load_dataset('rgbsg.h5', partition=partition, **kwargs)

#%%
def load_simulated_gaussian(partition='complete', **kwargs):
    """
    Synthetic data with a Gaussian (non-linear) log-risk function.

    For more information, see [#katzman1]_ as well as the accompanying README.

    Parameters
    ----------
    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#katzman1] Katzman, Jared L., et al. "DeepSurv: personalized treatment recommender system using a Cox proportional hazards deep neural network." BMC medical research methodology 18.1 (2018): 24.
    """
    return _load_dataset('simulated_gaussian.h5', partition=partition, **kwargs)

#%%
def load_simulated_linear(partition='complete', **kwargs):
    """
    Synthetic data with a linear log-risk function.

    For more information, see [#katzman2]_ as well as the accompanying README.

    Parameters
    ----------
    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#katzman2] Katzman, Jared L., et al. "DeepSurv: personalized treatment recommender system using a Cox proportional hazards deep neural network." BMC medical research methodology 18.1 (2018): 24.
    """
    return _load_dataset('simulated_linear.h5', partition=partition, **kwargs)

#%%
def load_simulated_treatment(partition='complete', **kwargs):
    """
    Synthetic data similar to the simulated_gaussian one, with an additional
    column representing treatment.

    For more information, see [#katzman3]_ as well as the accompanying README.

    Parameters
    ----------
    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#katzman3] Katzman, Jared L., et al. "DeepSurv: personalized treatment recommender system using a Cox proportional hazards deep neural network." BMC medical research methodology 18.1 (2018): 24.
    """
    return _load_dataset('simulated_treatment.h5', partition=partition, **kwargs)

#%%
def load_support(partition='complete', **kwargs):
    """
    Data from the Study to Understand Prognoses Preferences Outcomes
    and Risks of Treatment (SUPPORT), which studied the survival time of
    seriously ill hospitalized adults.

    Originally, it consists of 14 clinical features of 9105 patients.
    However, patients with missing features were dropped, leaving a total
    of 8873 patients.

    For more information, see [#knaus]_ as well as the accompanying README.

    Parameters
    ----------
    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#knaus] Knaus, William A., et al. "The SUPPORT prognostic model: Objective estimates of survival for seriously ill hospitalized adults." Annals of internal medicine 122.3 (1995): 191-203.
    """
    return _load_dataset('support.h5', partition=partition, **kwargs)

#%%
def load_whas(partition='complete', **kwargs):
    """
    Data from the Worcester Heart Attack Study (WHAS), which investigates
    the effects of a patient's factors on acute myocardial infraction (MI)
    survival.

    It consists of 1638 observations and 5 features: age, sex,
    body-mass-index (BMI), left heart failure complications (CHF), and order
    of MI (MIORD).

    For more information, see [#hosmer]_ as well as the accompanying README.

    Parameters
    ----------
    partition: string
        Partition of the data to load.

        Possible values are:
            * ``complete`` - The whole dataset (default)
            * ``training`` or ``train`` - Training partition as used in the original DeepSurv
            * ``testing`` or ``test`` - Testing partition as used in the original DeepSurv

    data_type: string
        Data type of the data.

        Possible values are:
            * ``pandas`` or ``pd`` or ``dataframe`` or ``df``- pandas DataFrame (default)
            * ``numpy`` or ``np`` - NumPy array

        .. note::
            NumPy is supported as an option, but DeepSurvK is built
            with pandas in mind.

    Returns
    -------
    tuple of pandas DataFrames
        * X - Features
        * Y - Target variable
        * E - Event variable

    References
    ----------
    .. [#hosmer] Hosmer Jr, David W., Stanley Lemeshow, and Susanne May. Applied survival analysis: regression modeling of time-to-event data. Vol. 618. John Wiley & Sons, 2011.
    """
    return _load_dataset('whas.h5', partition=partition, **kwargs)


import sys
import os
import random
from .files import FileManager

FIRSTNAME_DATA_FILE = '/../../data/firstname.txt'
LASTNAME_DATA_FILE = '/../../data/lastname.txt'
DOMAIN_DATA_FILE = '/../../data/domain.txt'

class EmailManager:
    def __init__(self):
        fileManager = FileManager((os.path.dirname(__file__) or '.'))
        self.firstnames = fileManager.loadTextFile(FIRSTNAME_DATA_FILE)
        self.lastnames = fileManager.loadTextFile(LASTNAME_DATA_FILE)
        self.domains = fileManager.loadTextFile(DOMAIN_DATA_FILE)

    def getRandomEmail(self, addUid=random.choice([False, True])):
        uid = ''
        if addUid:
            uid = str(random.randint(100, 999))
        firstname = random.choice(self.firstnames)
        lastname = random.choice(self.lastnames)

        email = '{firstname}{separator}{lastname}{uid}@{domain}'.format(
            uid=uid,
            firstname=firstname,
            lastname=lastname,
            domain=random.choice(self.domains),
            separator=random.choice(['.', '-', '_', ''])
        )
        return {
            'email': email,
            'firstname': firstname,
            'lastname': lastname
        }


import pygame
import projectiles
import utilities
import assets

class Weapon():
    def __init__(self):
        self.projectile = None
        self.rate_of_fire = None
        self.accuracy = None
        self.ammo_type = None
        self.current_ammo = None
        self.mag_size = None
        self.current_mag = None
        self.automatic = False
        self.loaded = True
        self.empty_sound = assets.empty_sound

    def fire(self, current_level, pos, player_x, player_y, player):
        origin_modifier = {6: (30, -10), 5: (55, 5), 4: (55, 15), 3: (60, 20), 2: (50, 30), 1: (45, 40), 0: (10, 60)}
        new_projectile = projectiles.Bullet()
        vector_mod = origin_modifier[player.arm_state]
        new_projectile.rect.x = player_x + vector_mod[0]
        new_projectile.rect.y = player_y + vector_mod[1]
        x = pos[0] + 15
        y = pos[1] + 15
        if pos[0] < player_x + 65:
            x = player_x + 65
        assets.pistol_shot_sound.play()
        vector = utilities.get_vector(new_projectile, x, y, new_projectile.rect.x, new_projectile.rect.y)
        new_projectile.change_x = vector[0]
        new_projectile.change_y = vector[1]
        current_level.projectiles_list.add(new_projectile)
        player.firing = self.automatic
        self.current_mag -= 1
        if self.current_mag == 0:
            self.loaded = False

class Pistol(Weapon):
    def __init__(self):
        super().__init__()
        self.projectile_type = type(projectiles.Bullet)
        self.automatic = False
        self.mag_size = 10
        self.current_mag = 10
        self.current_ammo = 1000

pistol = Pistol()

weapons = [pistol]


""" This module holds a torch nn.module sublass for 2D UNets.

by Stefan Schmohl, 2020
"""

import torch
import torch.nn as nn
import sparseconvnet as scn

#class Conv2dSamePadding(nn.Conv2d):
    #"""
    #https://gist.github.com/sumanmichael/4de9dee93f972d47c80c4ade8e149ea6
    #"""
    #def __init__(self,*args,**kwargs):
        #super(Conv2dSamePadding, self).__init__(*args, **kwargs)
        #self.zero_pad_2d = nn.ZeroPad2d[(k // 2) for k in self.kernel_size[::-1]]))

    #def forward(self, input):
        #return  self._conv_forward(self.zero_pad_2d(input), self.weight, self.bias)

class SUNet2D(nn.Module):
    """ Class for a neural network in  U-Net architecture.

    __init__() provides convenient setup utilizing the U-Net generator.
    """

    @classmethod
    def from_config(cls, config):
        nIn = len(config['model']['input_features'])
        noC = len(config['model']['classes'])
        net = cls(**config['model']['network']['net-params'], nIn=nIn, noC=noC)
        return net

    def __init__(self, nIn, noC, input_size, filter_size, bias,
                 residual_blocks, downsample, reps, nPlanes, leakiness=0):
        """
        Args:
            nIn:
                Number of input features.
            noC:
                Number of output classes.
            input_size:
                Spatial input size of samples. Note: only important for the
                framework to check, wheather there is to much downsampling
                happening (apparently).
            filter_size:
                Size of conv-filters, except for down- and upconv layers. One
                value, for all dims.
            bias:
                True / False for neurons to have bias weight.
            residual_block:
                True / False if conv-blocks should be redisual. My experience
                tells to better set to False.
            downsample:
                [filter_size, stride] for down- and upconv layers.
            reps:
                Number of conv layers per Unet block.
            nPlanes:
                Filter number per Unet level. The length defines the depth of
                the network, while the values define the depth.
        """

        super().__init__()

        m = nPlanes[0]  # Base filterbank size.

        self.Model = nn.Sequential(
            nn.Conv2d(nIn, m, filter_size, bias=bias, padding=filter_size//2),
            UNet2D(reps, nPlanes, residual_blocks, downsample, filter_size,
                   bias, leakiness),
            nn.BatchNorm2d(m),
            nn.LeakyReLU(leakiness))

        # 1x1x1 Convolutions in Semantic Segmentation,
        self.linear = nn.Sequential(nn.Conv2d(m, m*3, kernel_size=1),
                                    nn.BatchNorm2d(m*3),
                                    nn.LeakyReLU(leakiness),
                                    nn.Dropout(p=0.5),
                                    nn.Conv2d(m*3, noC, kernel_size=1))
    def forward(self, x):
        x = x[1]  # [1] is data, [0] are coords
        x = self.Model(x)
        x = self.linear(x)
        return x

def UNet2D(reps, nPlanes, residual_blocks=False, downsample=[2, 2],
           filter_size=3, bias=False, leakiness=0, n_input_planes=-1):

    global c
    c = 0

    def block(m, a, b):
        global c
        if residual_blocks: #ResNet style blocks
            raise Exception("not implemented yet")
        else: #VGG style blocks
            m.add_module('batchnorm2d_{}'.format(c), nn.BatchNorm2d(a)); c+=1;
            m.add_module('leakyRelu_{}'.format(c), nn.LeakyReLU(leakiness)); c+=1;
            m.add_module('Conv2d_{}'.format(c), nn.Conv2d(a, b, filter_size, bias=bias, padding=filter_size//2)); c+=1;

    class U(nn.Module):
        def __init__(self,nPlanes,n_input_planes=-1): #Recursive function
            super(U, self).__init__()

            left = nn.Sequential()
            for i in range(reps):
                block(left, n_input_planes if n_input_planes!=-1 else nPlanes[0], nPlanes[0])
                n_input_planes=-1

            if len(nPlanes) > 1:
                mid = U(nPlanes[1:])

                down = nn.Sequential(
                            nn.BatchNorm2d(nPlanes[0]),
                            nn.LeakyReLU(leakiness),
                            nn.Conv2d(nPlanes[0], nPlanes[1],
                                downsample[0], downsample[1], bias=bias))

                up = nn.Sequential(
                            nn.BatchNorm2d(nPlanes[1]),
                            nn.LeakyReLU(leakiness),
                            nn.ConvTranspose2d(nPlanes[1], nPlanes[0],
                                downsample[0], downsample[1], bias=bias))

                right = nn.Sequential()
                for i in range(reps):
                    block(right, nPlanes[0] * (2 if i == 0 else 1), nPlanes[0])

            else:
                down   = None
                mid    = None
                up     = None
                right  = None
            self.left   = left
            self.down   = down
            self.mid    = mid
            self.up     = up
            self.right  = right

        def join(self, input):
            return torch.cat(input, dim=1)

        def forward(self, inputs):
            l = self.left(inputs)
            if self.right is None:
                return l

            d    = self.down(l)
            m    = self.mid(d)
            u    = self.up(m)
            j    = self.join([l,u])
            r    = self.right(j)
            return r

    m = U(nPlanes,n_input_planes)
    return m


import cv2
import numpy as np
cam=cv2.VideoCapture(0)
p1_x=(int)(cam.get(cv2.CAP_PROP_FRAME_WIDTH)*3//4)
p1_y=(int)(cam.get(cv2.CAP_PROP_FRAME_HEIGHT)*3.5//4)
p2_x=(int)(cam.get(cv2.CAP_PROP_FRAME_WIDTH)//4)
p2_y=(int)(cam.get(cv2.CAP_PROP_FRAME_HEIGHT)//4)
while True:
    ret, im =cam.read()
    cv2.rectangle(im,pt1=(p2_x,p2_y),pt2=(p1_x,p1_y),color=(0,0,255),thickness=5)
    cv2.imshow('im',im)
    if cv2.waitKey(10) & 0xFF==ord('q'):
        break

cam.release()
cv2.destroyAllWindows()


import requests

SHEETY_API_URL = "https://api.sheety.co"
SHEET_URL = "/f67b10a3d7cc6477d8bac06b1ce12143/flightDeals/"
SHEETY_TOKEN = "Flightdealsapibyyogi"

class DataManager:

    def __init__(self, worksheet_name):
        self.worksheet_name = worksheet_name
        self.worksheet_url = SHEETY_API_URL + SHEET_URL + self.worksheet_name
        self.headers = {
            "Authorization": f"Bearer {SHEETY_TOKEN}"
        }

    def get_sheet(self):
        """Takes a worksheet name as STR, retrieves it and returns the rows as a LIST."""
        response = requests.get(url=self.worksheet_url, headers=self.headers)
        # just raise an error, not handling exceptions for now
        response.raise_for_status()
        # to have some feedback
        print(f"Worksheet \"{self.worksheet_name}\" successfully loaded.")
        return response.json()[self.worksheet_name]

    def update_destination_codes(self, city):
        code_url = f"{self.worksheet_url}/{city['id']}"
        new_data = {
            "price": {
                "iataCode": city["iataCode"]
            }
        }
        response = requests.put(
            url=code_url,
            json=new_data,
            headers=self.headers
        )
        response.raise_for_status()
        print(f"Row {city['id']} has been updated with code {city['iataCode']}.")

    def add_user(self, first_name, last_name, email):
        """Takes the user's details as STRs and add them to the worksheet."""
        body = {
            "user": {
                "firstName": first_name,
                "lastName": last_name,
                "email": email
            }
        }
        response = requests.post(url=self.worksheet_url, json=body, headers=self.headers)
        # also just raise an error
        response.raise_for_status()
        # also to have some feedback
        print(f"User {first_name} {last_name} has been added to the \"{self.worksheet_name}\" worksheet.")


import sys
import torch.backends.cudnn as cudnn
import argparse
import logging
from PointMLP.segmentation.model.PointMLP import *
from PointMLP.data_util.ShapeNetDataloader import *
from PointMLP.utils import *

def parse_args(args=None):

    parser = argparse.ArgumentParser(description='3D Shape Part Segmentation')
    parser.add_argument('--model', type=str, default='PointMLP1')
    parser.add_argument('--exp_name', type=str, default='demo1', metavar='N',
                        help='Name of the experiment')
    parser.add_argument('--batch_size', type=int, default=16, metavar='batch_size',
                        help='Size of batch)')
    parser.add_argument('--test_batch_size', type=int, default=16, metavar='batch_size',
                        help='Size of batch)')
    parser.add_argument('--epochs', type=int, default=350, metavar='N',
                        help='number of episode to train')
    parser.add_argument('--gpu', type=str, default='0', help='specify GPU devices')
    parser.add_argument('--use_sgd', type=bool, default=False,
                        help='Use SGD')
    parser.add_argument('--scheduler', type=str, default='step',
                        help='lr scheduler')
    parser.add_argument('--step', type=int, default=40,
                        help='lr decay step')
    parser.add_argument('--lr', type=float, default=0.003, metavar='LR',
                        help='learning rate')
    parser.add_argument('--momentum', type=float, default=0.9, metavar='M',
                        help='SGD momentum (default: 0.9)')
    parser.add_argument('--no_cuda', type=bool, default=False,
                        help='enables CUDA training')
    parser.add_argument('--manual_seed', type=int, metavar='S',
                        help='random seed (default: 1)')
    parser.add_argument('--eval', type=bool,  default=False,
                        help='evaluate the model')
    parser.add_argument('--num_points', type=int, default=2048,
                        help='num of points to use')
    parser.add_argument('--workers', type=int, default=12)
    parser.add_argument('--resume', type=bool, default=False,
                        help='Resume training or not')
    parser.add_argument('--model_type', type=str, default='insiou',
                        help='choose to test the best insiou/clsiou/acc model (options: insiou, clsiou, acc)')

    return parser.parse_args(args)

# 传入命令行参数
sys.argv = ['--batch_size', '--epoch','350','--gpu', '7']
args = parse_args()
print(args)

assert torch.cuda.is_available(), "Please ensure codes are executed in cuda."
# device = torch.device("cuda:5" if torch.cuda.is_available() else "cpu")
torch.cuda.set_device(int(args.gpu))

num_part = 50
# device = torch.device("cuda" if args.cuda else "cpu")

# io.cprint(str(model))
model = PointMLP(num_part).cuda()
# model = model.to(device)

model.apply(weight_init)

if args.use_sgd:
    print("Use SGD")
    opt = optim.SGD(model.parameters(), lr=args.lr*100, momentum=args.momentum, weight_decay=0)
else:
    print("Use Adam")
    opt = optim.Adam(model.parameters(), lr=args.lr, betas=(0.9, 0.999), eps=1e-08, weight_decay=0)

if args.scheduler == 'cos':
    print("Use CosLR")
    scheduler = CosineAnnealingLR(opt, args.epochs, eta_min=args.lr if args.use_sgd else args.lr / 100)
else:
    print("Use StepLR")
    scheduler = StepLR(opt, step_size=args.step, gamma=0.5)

best_acc = 0
best_class_iou = 0
best_instance_iou = 0
num_part = 50
num_classes = 16

train_dataset = PartNormalDataset(root=data_path, npoints=args.num_points, split='trainval', normal_channel=False)
test_dataset = PartNormalDataset(root=data_path, npoints=args.num_points, split='test', normal_channel=False)

trainDataLoader = torch.utils.data.DataLoader(train_dataset, batch_size=args.batch_size, shuffle=True, num_workers=10, drop_last=True)
testDataLoader = torch.utils.data.DataLoader(test_dataset, batch_size=args.batch_size, shuffle=False, num_workers=10)

def train_epoch(train_loader, model, opt, scheduler, epoch, num_part, num_classes):
    train_loss = 0.0
    total_loss = 0
    count = 0.0
    accuracy = []
    shape_ious = 0.0
    metrics = {}
    model.train()

    for batch_id, (points, label, target, norm_plt) in tqdm(enumerate(train_loader), total=len(train_loader),
                                                            smoothing=0.9):
        batch_size, num_point, _ = points.size()

        points, label, target, norm_plt = points.float().cuda(), label.long().squeeze(1).cuda(), target.long().cuda(), \
                                          norm_plt.float().cuda()
        points = points.transpose(2, 1)
        norm_plt = norm_plt.transpose(2, 1)

        # target: b,n
        seg_pred = model(points, norm_plt, to_categorical(label, num_classes))  # seg_pred: b,n,50
        loss = F.nll_loss(seg_pred.contiguous().view(-1, num_part), target.view(-1, 1)[:, 0])

        # instance iou without considering the class average at each batch_size:
        batch_shapeious = compute_overall_iou(seg_pred, target,
                                              num_part)  # list of of current batch_iou:[iou1,iou2,...,iou#b_size]
        # total iou of current batch in each process:
        batch_shapeious = seg_pred.new_tensor([np.sum(batch_shapeious)],
                                              dtype=torch.float64)  # same device with seg_pred!!!

        # Loss backward
        loss = torch.mean(loss)
        opt.zero_grad()
        loss.backward()
        opt.step()

        # accuracy
        seg_pred = seg_pred.contiguous().view(-1, num_part)
        target = target.view(-1, 1)[:, 0]
        pred_choice = seg_pred.contiguous().data.max(1)[1]
        correct = pred_choice.eq(target.contiguous().data).sum()

        # sum
        shape_ious += batch_shapeious.item()
        count += batch_size
        train_loss += loss.item() * batch_size
        accuracy.append(correct.item() / (batch_size * num_point))

    if args.scheduler == 'cos':
        scheduler.step()
    elif args.scheduler == 'step':
        if opt.param_groups[0]['lr'] > 0.9e-5:
            scheduler.step()
        if opt.param_groups[0]['lr'] < 0.9e-5:
            for param_group in opt.param_groups:
                param_group['lr'] = 0.9e-5

    lr = opt.param_groups[0]['lr']
    printf('Learning rate: %f' % opt.param_groups[0]['lr'])

    train_avg_loss = train_loss * 1.0 / count

    metrics['accuracy'] = np.mean(accuracy)
    train_avg_acc = metrics['accuracy']

    metrics['shape_avg_iou'] = shape_ious * 1.0 / count
    train_avg_iou = metrics['shape_avg_iou']

    outstr = 'Train %d, loss: %f, train acc: %f, train ins_iou: %f' % (epoch + 1, train_avg_loss,
                                                                       train_avg_acc, train_avg_iou)
    printf(outstr)
    return train_avg_loss, train_avg_acc, train_avg_iou, lr

train_loss, train_acc, train_iou, val_loss, val_acc, val_iou, val_class_iou, lr_history = [], [], [], [], [], [], [], []

classes_str = ['aero','bag','cap','car','chair','ear','guitar','knife','lamp','lapt','moto','mug','Pistol','rock','stake','table']

for epoch in range(args.epochs):

    train_avg_loss, train_avg_acc, train_avg_iou, lr = train_epoch(trainDataLoader, model, opt, scheduler, epoch,
                                                                   num_part, num_classes)
    lr_history.append(lr)
    train_loss.append(train_avg_loss)
    train_acc.append(train_avg_acc)
    train_iou.append(train_avg_iou)

    test_avg_loss, test_metrics, total_per_cat_iou = test_epoch(testDataLoader, model, epoch, num_part, num_classes)
    val_loss.append(test_avg_loss)
    val_acc.append(test_metrics['accuracy'])
    val_iou.append(test_metrics['shape_avg_iou'])

    if test_metrics['accuracy'] > best_acc:
        best_acc = test_metrics['accuracy']
        printf('Max Acc:%.5f' % best_acc)

    if test_metrics['shape_avg_iou'] > best_instance_iou:
        best_instance_iou = test_metrics['shape_avg_iou']
        printf('Max instance iou:%.5f' % best_instance_iou)

    class_iou = 0
    for cat_idx in range(16):
        class_iou += total_per_cat_iou[cat_idx]
    avg_class_iou = class_iou / 16
    val_class_iou.append(avg_class_iou)

    if avg_class_iou > best_class_iou:
        best_class_iou = avg_class_iou
        # print the iou of each class:
        for cat_idx in range(16):
            printf(classes_str[cat_idx] + ' iou: ' + str(total_per_cat_iou[cat_idx]))
        printf('Max class iou:%.5f' % best_class_iou)

printf('Final Max Acc:%.5f' % best_acc)
printf('Final Max instance iou:%.5f' % best_instance_iou)
printf('Final Max class iou:%.5f' % best_class_iou)


SAMPLE_IPMI_SEL_ENTRIES = [
    {
        "ID": "493",
        "Date": "Oct-06-2022",
        "Time": "19:47:13",
        "Name": "System Board ACPI_Stat",
        "Type": "System ACPI Power State",
        "State": "Nominal",
        "Event": "S0/G0",
    },
    {
        "ID": "494",
        "Date": "Oct-06-2022",
        "Time": "19:57:23",
        "Name": "System Chassis SysHealth_Stat",
        "Type": "Chassis",
        "State": "Critical",
        "Event": "transition to Non-recoverable from less severe",
    },
    {
        "ID": "495",
        "Date": "Oct-06-2022",
        "Time": "19:57:38",
        "Name": "System Board ACPI_Stat",
        "Type": "System ACPI Power State",
        "State": "Warning",
        "Event": "S4/S5 soft-off",
    },
    {
        "ID": "496",
        "Date": "Oct-06-2022",
        "Time": "19:57:51",
        "Name": "System Board ACPI_Stat",
        "Type": "System ACPI Power State",
        "State": "Nominal",
        "Event": "S0/G0",
    },
    {
        "ID": "497",
        "Date": "Oct-06-2022",
        "Time": "19:57:51",
        "Name": "System Board ACPI_Stat",
        "Type": "System ACPI Power State",
        "State": "N/A",
        "Event": "S0/G0",
    },
]
SAMPLE_IPMI_SENSOR_ENTRIES = [
    {
        "ID": "0",
        "Name": "UID",
        "Type": "OEM Reserved",
        "State": "N/A",
        "Reading": "N/A",
        "Units": "N/A",
        "Event": "'OEM Event = 0001h'",
    },
    {
        "ID": "1",
        "Name": "SysHealth_Stat",
        "Type": "Chassis",
        "State": "Nominal",
        "Reading": "N/A",
        "Units": "N/A",
        "Event": "'transition to OK'",
    },
    {
        "ID": "2",
        "Name": "01-Inlet Ambient",
        "Type": "Temperature",
        "State": "Nominal",
        "Reading": "20.00",
        "Units": "C",
        "Event": "'OK'",
    },
    {
        "ID": "3",
        "Name": "Power Meter",
        "Type": "Other Units Based Sensor",
        "State": "Nominal",
        "Reading": "0.00",
        "Units": "W",
        "Event": "'OK'",
    },
    {
        "ID": "4",
        "Name": "Current meter",
        "Type": "Current",
        "State": "Nominal",
        "Reading": "22.00",
        "Units": "A",
        "Event": "'OK'",
    },
    {
        "ID": "5",
        "Name": "Fan meter",
        "Type": "Fan",
        "State": "Nominal",
        "Reading": "2200.00",
        "Units": "RPM",
        "Event": "'OK'",
    },
    {
        "ID": "6",
        "Name": "Volt Meter",
        "Type": "Other Units Based Sensor",
        "State": "Nominal",
        "Reading": "220.00",
        "Units": "V",
        "Event": "'OK'",
    },
    {
        "ID": "6",
        "Name": "Fan Meter",
        "Type": "Fan",
        "State": "Nominal",
        "Reading": "61.00",
        "Units": "%",
        "Event": "'OK'",
    },
    {
        "ID": "6",
        "Name": "Test meter",
        "Type": "Sample generic sensor",
        "State": "Nominal",
        "Reading": "54.00",
        "Units": "%",
        "Event": "'OK'",
    },
]


"""
заполнение спиралью матрицы n на m
"""

"""
Я обычно ставлю метки на границы и их аккуратно пытаюсь двигать.
Много проще заполнить все нулями или Noneами и разворачиваться,
когда дошли до границы или уже заполненных ячеек.
"""

# n, m = map(int, input().split())
N, M = 5, 7
lst = [[None] * M for _ in range(N)]
cnt = 0
row = 0
col = -1
while cnt < N * M:

    """
    Бежим по верхней строке вправо и заполняем каунтами пока либо не упремся в стенку
    (это будет только в первый раз), либо не наткнемся на уже заполненную часть матрицы
    (там не Noneы).
    Вообще можно короче написать: while lst[row][(col + 1) % m] is None.
    В ячейке [0][0] уже не None.
    """
    while col < M - 1 and lst[row][col + 1] is None:
        col += 1
        cnt += 1
        lst[row][col] = cnt

    while row < N - 1 and lst[row + 1][col] is None:  # справа бежим вниз
        row += 1
        cnt += 1
        lst[row][col] = cnt

    """
    Можно отказаться от проверки на границу, все итак сработает: в ячейке [row][-1] уже не None.
    Достаточно: while lst[row][col - 1] is None
    """
    while col > 0 and lst[row][col - 1] is None:  # снизу бежим влево
        col -= 1
        cnt += 1
        lst[row][col] = cnt

    while row > 0 and lst[row - 1][col] is None:  # слева бежим вверх
        row -= 1
        cnt += 1
        lst[row][col] = cnt

[print(*r) for r in lst]

"""
ИДЕИ РЕШЕНИЯ
Заполнять прямоугольниками, начиная с ячейки [0][0], потом [1][1] и т.д.
Сделать один цикл от 1 до n * m и внутри него по условию менять "угол" с которого идем и шаги:
    (1, 0) -> (0, 1) -> (-1, 0) -> (0, -1) -> ...

ЧАСТНОСТИ
Заполнить матрицу нулями и заполнять ее ориентируясь на нули.
"""


import hashlib
from django.db import models
from django.contrib.auth.models import User, Group

INSTALLABLE_TYPES = (
    (0, 'tool'),
    (1, 'datatype'),
    (2, 'suite'),
    (3, 'viz'),
    (4, 'gie')
    # Wow I miss golang's iota. Just look at that! https://github.com/golang/go/wiki/Iota
)

PACKAGE_TYPES = (
    (0, 'conda'),
)

class UserExtension(models.Model):
    """Extension to the built-in user model, with a 1:1 mapping to users.
    """
    user = models.OneToOneField(User, primary_key=True)
    display_name = models.CharField(max_length=64, blank=True)
    api_key = models.CharField(max_length=32, unique=True, blank=True)
    gpg_pubkey_id = models.CharField(max_length=16)
    github = models.IntegerField()

    @property
    def hashedEmail(self):
        """Return an md5sum digest of the email address, appropriate for
        gravatars

        TODO: convert to a model field, we can denormalize a bit for not
        calculating a gazillion md5sums
        """
        return hashlib.md5(self.user.email).hexdigest()

    @property
    def gravatar_url(self):
        return '//www.gravatar.com/avatar/' + self.hashedEmail

    def __str__(self):
        return '%s <%s>' % (self.display_name, self.user.email)

class GroupExtension(models.Model):
    """Extension to the built-in group model, with a 1:1 mapping to groups.
    """
    group = models.OneToOneField(Group, primary_key=True)

    description = models.TextField(blank=False)
    website = models.TextField()
    gpg_pubkey_id = models.CharField(max_length=16)

    def __str__(self):
        return self.group.name

class Tag(models.Model):
    """User managed tags replace admin managed categories
    """
    display_name = models.CharField(max_length=120, blank=False)
    description = models.TextField(blank=False)

    def __str__(self):
        return self.display_name

class Installable(models.Model):
    """A single installable thing, equivalent to a repository in the old TS.

    Installables represent the repository level "thing", while Versions
    represent the real concrete installable version of a "thing".

    Installables have the usual metadata associated with TS repos, a set of
    tags, and then a set of users and groups with permissions to edit this
    repository. Being granted access to a repository grants the ability to change
    repository metadata, and to create new versions (releases).
    """
    # TODO: prevent renaming
    name = models.CharField(max_length=120, blank=False)
    synopsis = models.TextField(blank=False)
    description = models.TextField(blank=False)

    remote_repository_url = models.URLField()
    homepage_url = models.URLField()

    repository_type = models.IntegerField(choices=INSTALLABLE_TYPES, blank=False)

    tags = models.ManyToManyField(Tag)

    owner = models.ForeignKey(User, related_name='creator')
    user_access = models.ManyToManyField(User, blank=True)
    group_access = models.ManyToManyField(Group, blank=True)

    def can_edit(self, user):
        """Is the user allowed to edit the repo.

        This method will check a direct user access level, as well as via groups.
        """
        if user == self.owner:
            return True

        if user in self.user_access.all():
            return True

        for group in user.groups.all():
            if group in self.group_access.all():
                return True

        return False

    @property
    def total_downloads(self):
        """Query to find the sum of downloads for each version
        """
        return sum([
            rev.downloads for rev in self.version_set.all()
        ])

    @property
    def last_updated(self):
        """Return the upload date of the most recent version
        """
        v = self.latest_version
        if v is None:
            return None
        else:
            return v.uploaded

    @property
    def latest_version(self):
        """Return the upload date of the most recent version
        """
        if self.version_set.all().exists():
            return self.version_set.order_by('-uploaded').first()
        else:
            return None

    @property
    def namespace(self):
        return '.'.join([
            'galaxyproject',
            'shed',
            self.owner.username,
            self.name
        ])

    def __str__(self):
        return self.name

class PackageDependency(models.Model):
    """PackageDependencies are external dependencies not tracked by the TS.
    """
    type = models.IntegerField(choices=PACKAGE_TYPES, blank=False)
    identifier = models.CharField(max_length=32)
    package_version = models.CharField(max_length=16)

    class Meta:
        verbose_name_plural='Package dependencies'

    def __str__(self):
        return '{0.identifier}=={0.package_version}'.format(self)

class Version(models.Model):
    """A single version/version/release of a repository.

    In the old system, changeset IDs were the unique component of a version.
    We're replacing that with the actual version encoded in the file, and the
    hard requirement that they absolutely must be unique within an installable.
    This means we can get rid of two ugly identifiers (``version.id``,
    ``version.changeset_id``) and replace with a single human-readable
    ``version.version``.

    Versions must have an sha256sum, generated on the server side,
    hopefully checked against the uploading client. This is to provide
    transport integrity.

    Versions may have a GPG signature associated to them, signed with a user
    or group GPG key.

    Versions may specify a replacement version. I haven't fully figured out
    how I want that to work, but essentially it should point to the version
    you should upgrade to from the version you're currently looking at. Say
    Alice, Bob, and Charlie all have a different implementation of foobar 0.12,
    in the heydey of tool development. They recognise that this is a problem,
    and band together as the Galaxy foobar developers in a group. With the
    release of foobar 1.0, they've coordinated a great DatasetCollection
    enabled version of the foobar package and make a single release. At that
    time, they can adjust all of their individual repositories to say "point to
    foobar 1.0 from group bazqux." On the Galaxy admin side, it should simply
    say something like "Upgrade foobar 0.12 from Alice" and "The administrator
    foobar 0.12 from Alice's repository has specified that their version is
    replaced with foobar 1.0 from bazqux" giving the admin some assurance that
    this is intended.

    Versions may have dependencies. These are not really user-editable online,
    and must be parsed from tool_dependencies.xml files. This is stored as an
    asymmetrical adjacency table. Versions point to other versions.
    """
    # This must be unique per installable.
    version = models.CharField(max_length=12, blank=False)
    commit_message = models.TextField(blank=False)
    uploaded = models.DateTimeField(blank=False)
    # Link back to our parent installable
    installable = models.ForeignKey(Installable, blank=False)
    # Archive sha256sum for transport integrity
    tar_gz_sha256 = models.CharField(max_length=64)
    # No need to store in an API accessible manner, just on disk.
    # Maybe should have a toolshed GPG key and sign all packages with that.
    tar_gz_sig_available = models.BooleanField(default=False, blank=False)

    # If a user has this version of this package installed, what should they
    # upgrade to. Need to provide a (probably expensive) method to calculate a
    # full upgrade path?
    replacement_version = models.ForeignKey('self', blank=True, null=True, related_name='upgrade_to')

    # Track downloads
    downloads = models.IntegerField(default=0)

    # Dependency graph data
    dependencies = models.ManyToManyField(
        'self',
        through='VersionDependency',
        blank=True,
        symmetrical=False,
        related_name='used_in'
    )

    # Conda dependencies
    package_dependencies = models.ManyToManyField(PackageDependency)

    @property
    def namespace(self):
        return (self.installable.namespace, self.version)

    def __str__(self):
        return '%s %s' % (self.installable.name, self.version)

class VersionDependency(models.Model):
    """Linking table for versions.

    This may not be needed, but everything works? So we're not touching it.
    Maybe someone will have metadata they wish to add to dependencies later on.
    """
    from_version = models.ForeignKey(Version, related_name='from_version')
    to_version = models.ForeignKey(Version, related_name='to_version')

    def __str__(self):
        return 'dependency %s -> %s' % (self.from_version, self.to_version)

class SuiteVersion(models.Model):
    """SuiteVersions are a bit special: they're like an Version in that they
    have a parent installable, and that a SuiteVersion represents a single
    iteration of a suite. However, since they're metapackages and lack
    downloadables, they're unlike versions enough that we have to separate the
    model out.

    This feels like a very weak rationalization. Maybe suites should be
    completely removed and just merged with versions.
    """
    version = models.CharField(max_length=12, blank=False)
    commit_message = models.TextField(blank=False)
    installable = models.ForeignKey(Installable)
    contained_versions = models.ManyToManyField(Version)

    def __str__(self):
        return 'Suite %s %s' % (self.installable.name, self.version)


name = "aabbbccde"
all=[]
dict={}

for i in range(len(name)):         #Converts the string to a list
    all.append(name[i])

for lett in all:
     dict.update({lett:all.count(lett)})       #Creates a dictionary with key as alphabets and value as frequency of letter also the duplicate letters are ignored.
print(dict)

all_item = dict.items()
sorted_items = sorted(all_item)    # Takes the key-value of dictionary and SORTS by KEY in form of tuples inside a list [('a', 2), ('b', 3), ('c', 2), ('d', 1), ('e', 1)]
print(sorted_items)

sorted_items.sort(key=lambda x: x[1],reverse=True)     # SORTS the tuples according to second value inside tuple. [('b', 3), ('a', 2), ('c', 2), ('d', 1), ('e', 1)]
print(sorted_items)

for i in range(3):
    print(sorted_items[i][0], sorted_items[i][1])   #


import sqlite3
import streamlit as st
import openai  # Assurez-vous que la bibliothÃ¨que OpenAI est installÃ©e et configurÃ©e
import sys
import os
from io import StringIO
from dotenv import load_dotenv

# Charger la clÃ© API OpenAI Ã  partir du fichier .env situÃ© dans le rÃ©pertoire config
load_dotenv(dotenv_path='../config/.env')

# Configurer la clÃ© API OpenAI
openai.api_key = os.getenv("OPENAI_API_KEY")

def python_openai_api(prompt_human: str):
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[
            {"role": "system", "content": "You are a helpful assistant."},
            {"role": "user", "content": f"Sans explication hors code, sans commentaire, traduire le texte suivant en code Python : {prompt_human}"}
        ],
        temperature=0.4,
        max_tokens=256,
        top_p=1,
        frequency_penalty=0,
        presence_penalty=0
    )
    return response['choices'][0]['message']['content']

def create_tables():

    db_path = 'scripts.db'
    db_exists = os.path.exists(db_path)
    conn = sqlite3.connect(db_path)
    if not db_exists:
        # si la db n'existe pas

        c = conn.cursor()

        # CrÃ©ation de la table
        c.execute('''
        CREATE TABLE IF NOT EXISTS scripts_titres (
            ID INTEGER PRIMARY KEY,
            titre TEXT NOT NULL
        )
        ''')

        # CrÃ©ation de la table
        c.execute('''
        CREATE TABLE IF NOT EXISTS scripts_contenus (
            ID INTEGER PRIMARY KEY,
            txt_humain TEXT NOT NULL,
            cde_python TEXT NOT NULL,
            scripts_titre_id INTEGER,
            FOREIGN KEY (scripts_titre_id) REFERENCES scripts_titres (ID)
        )
        ''')

    conn.commit()
    conn.close()

def save_title_to_db(title):
    """
    Save the title to the 'scripts_titres' table in the database.
    """
    db_path = 'scripts.db'
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()

    # Insert or update the title in the 'scripts_titres' table
    cursor.execute("""
        INSERT OR REPLACE INTO scripts_titres (ID, titre)
        VALUES ((SELECT ID FROM scripts_titres WHERE titre = ?), ?)
    """, (title, title))

    # Committing the transaction and closing the connection
    conn.commit()
    conn.close()

def save_script(titre, txt_humain, cde_python):

    db_path = 'scripts.db'
    db_exists = os.path.exists(db_path)
    conn = sqlite3.connect(db_path)
    if db_exists:
        c = conn.cursor()
        c.execute('INSERT INTO scripts_titres (titre) VALUES (?)', (titre,))
        titre_id = c.lastrowid

        c.execute('INSERT INTO scripts_contenus (txt_humain, cde_python, scripts_titre_id) VALUES (?, ?, ?)',
                  (txt_humain, cde_python, titre_id))

    conn.commit()
    conn.close()

def get_titles_from_db():
    """
    Get all titles from the 'scripts_titres' table in the database.
    """
    db_path = 'scripts.db'
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()

    cursor.execute("SELECT titre FROM scripts_titres")
    titles = cursor.fetchall()

    # Committing the transaction and closing the connection
    conn.close()

    # Returning the titles as a list of strings
    return [title[0] for title in titles]

def get_script_from_db(title):
    """Get a script from the database based on the title."""
    db_path = 'scripts.db'
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()

    cursor.execute(
        "SELECT txt_humain, cde_python FROM scripts_contenus WHERE scripts_titre_id = (SELECT ID FROM scripts_titres WHERE titre = ?)", (title,))
    script = cursor.fetchone()

    conn.close()

    return script

st.title('Traducteur de texte en code Python')

script_title = st.text_input('Titre de mon script Python')

# CrÃ©ation de deux colonnes
col1, col2 = st.columns(2)

with col1:
    st.header('Texte humain')
    human_text = st.text_area('Entrez votre texte ici :', height=200)
    translate_button = st.button('Traduire en Python')

with col2:
    st.header('Code Python gÃ©nÃ©rÃ©')
    if translate_button and human_text:
        # Vous pouvez dÃ©commenter et utiliser cette ligne si vous avez les clÃ©s API d'OpenAI configurÃ©es.
        st.session_state.python_code = python_openai_api(human_text)
        # Ceci est une ligne temporaire.
        # st.session_state.python_code = 'Votre code traduit apparaÃ®tra ici.'

    python_code = st.text_area('Votre code traduit sera affichÃ© ici :',
                               value=st.session_state.get('python_code', ''), height=200)

    execute_button = st.button('ExÃ©cuter le code')

if execute_button and python_code:
    try:
        # Rediriger la sortie standard vers un tampon
        old_stdout = sys.stdout
        new_stdout = StringIO()
        sys.stdout = new_stdout

        exec(python_code)
        # RÃ©cupÃ©rer la sortie standard capturÃ©e
        output = new_stdout.getvalue()

        # Restaurer la sortie standard d'origine
        sys.stdout = old_stdout

        # CrÃ©er une zone pour afficher le rÃ©sultat
        st.subheader("RÃ©sultat de l'exÃ©cution ðŸ˜Š")
        st.text(output)

        st.subheader("Code saisi ðŸ˜Š")
        st.code(python_code, language="python")
        st.success('Le code a Ã©tÃ© exÃ©cutÃ© avec succÃ¨s.')
    except Exception as e:
        st.error(f'Une erreur est survenue : {e}')
    finally:
        st.info("Merci d'avoir utilisÃ© cette application !")

create_tables()

if st.button('Sauvegarder les changements'):
    # save_title_to_db(script_title)
    save_script(script_title, human_text, python_code)

titles = get_titles_from_db()
selected_title = st.sidebar.selectbox(
    'SÃ©lectionnez un script', options=get_titles_from_db(), key='selected_title')

# Si un titre est sÃ©lectionnÃ©, mettez Ã  jour les Ã©tats de session avec les valeurs du script sÃ©lectionnÃ©
if selected_title:
    selected_script = get_script_from_db(selected_title)
    if selected_script:
        st.session_state.script_title = selected_title
        st.session_state.human_text, st.session_state.python_code = selected_script
    else:
        st.session_state.script_title = st.session_state.human_text = st.session_state.python_code = ""
else:
    st.session_state.script_title = st.session_state.human_text = st.session_state.python_code = ""

# Utiliser les Ã©tats de session comme valeurs par dÃ©faut pour les widgets
script_title = st.text_input(
    'Titre de mon script Python', value=st.session_state.script_title)
human_text = st.text_area('Texte humain', value=st.session_state.human_text)
python_code = st.text_area(
    'Code Python gÃ©nÃ©rÃ©', value=st.session_state.python_code)

def display_tables():
    """
    Display the content of the 'scripts_titres' and 'scripts_contenus' tables.
    """
    db_path = 'scripts.db'
    conn = sqlite3.connect(db_path)
    cursor = conn.cursor()

    # Query and display the 'scripts_titres' table
    cursor.execute("SELECT * FROM scripts_titres")
    scripts_titres_data = cursor.fetchall()
    scripts_titres_columns = [column[0] for column in cursor.description]
    st.write("### Table 'scripts_titres'")
    st.write(scripts_titres_columns)
    st.write(scripts_titres_data)

    # Query and display the 'scripts_contenus' table
    cursor.execute("SELECT * FROM scripts_contenus")
    scripts_contenus_data = cursor.fetchall()
    scripts_contenus_columns = [column[0] for column in cursor.description]
    st.write("### Table 'scripts_contenus'")
    st.write(scripts_contenus_columns)
    st.write(scripts_contenus_data)

    # Closing the connection
    conn.close()

# Call this function where you want to display the tables in your Streamlit app
display_tables()


import numpy as np
import Functions.Python.setting_utils as su
import logging
import Functions.Python.MIND as pyMIND
import Functions.Python.uncertainty_features as ut
import Functions.Python.preprocessing as pre
import Functions.Python.landmark_utils as lu
import Functions.Python.ANTs.registration_ants as reg_ants
import Functions.Python.ANTs.loss_function as ants_loss

def main(current_experiment=None):
    where_to_run = 'local'  # 'local' , 'sharkCluster' , 'shark'
    database = 'DIR-Lab_COPD'
    current_experiment = 'elastix1'  # 'elastix1', 'ANTs1'
    if not su.load_setting(current_experiment, data=database, where_to_run=where_to_run):
        registration_method = 'ANTs'   # elastix , ANTs
        setting = su.initialize_setting(current_experiment, data=database, where_to_run=where_to_run, registration_method=registration_method)
    else:
        setting = su.load_setting(current_experiment, data=database, where_to_run=where_to_run)

    cn_list = setting['cn_range']
    feature_list = ['stdT', 'E_T', 'stdT_final', 'E_T_final', 'Jac', 'MIND', 'CV', 'NC', 'MI']
    feature_pool_list = ['stdT', 'E_T', 'stdT_final', 'E_T_final', 'Jac', 'MIND', 'CV']

    cn_remove = []
    for cn in cn_list:
        # ------------ pre-processing -------------
        pre.dirlab.dir_lab_copd(cn)
        pre.cylinder_mask(setting, cn=cn)
        pre.chest_segmentation.ptpulmo_segmentation_dirlab(data='DIR-Lab_COPD', cn=cn, segment_organ='Torso')
        pre.chest_segmentation.ptpulmo_segmentation_dirlab(data='DIR-Lab_COPD', cn=cn, segment_organ='Lung')
        pre.chest_segmentation.lung_fill_hole_dirlab(data='DIR-Lab_COPD', cn=cn)
        # pre.chest_segmentation.lung_fill_hole_erode(setting, cn=cn)
        # pre.cylinder_mask(setting, cn=cn, overwrite=False)
        pre.ants_preprocessing.image_normalization(setting, cn=cn)

        #  ------------ registration --------------
        # preferably do the registration by running either do_elastix_registration or do_ANTs_registration
        # do_elastix_registration

        # ------------ post-processing -------------
        reg_ants.convert_nii2mha(setting, cn=cn)

        # ---------- feature extraction -----------
        ut.std_t(setting, cn=cn, mode='initial')
        ut.std_t(setting, cn=cn, mode='final')
        ut.jac(setting, cn=cn)
        output_error = ut.compute_error(setting, cn=cn, write_error_image=True)
        if output_error == 2:
            cn_remove.append(cn)
        ut.ncmi(setting, cn=cn)
        ut.feature_pooling(setting, cn=cn, feature_list=feature_pool_list)

    cn_list = [cn for cn in cn_list if cn not in cn_remove]

    landmarks = lu.load_features(setting, feature_list=feature_list, cn_list=cn_list)
    exp_tre_list = ['elastix1-TRE_nonrigid', 'ANTs1-TRE_nonrigid']
    exp_loss = ['ANTs1']
    cn_list = setting['cn_range']
    lu.plot.boxplot_tre(setting, cn_list=cn_list, exp_tre_list=exp_tre_list)
    lu.plot.table_tre(setting, cn_list=cn_list, exp_tre_list=exp_tre_list)
    lu.plot.table_tre_cn(setting, cn_list=cn_list, exp='ANTs1-TRE_nonrigid')
    ants_loss.plot_loss(setting, cn_list=np.arange(1, 11), exp_list=exp_loss, out=0)

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)
    main(current_experiment=None)


import cv2 as cv

class MouseHandler:
    def __init__(self, window):
        self.state = [0, 0, 0]
        self.onMouseDown = None
        if window:
            cv.setMouseCallback(window, self.onMouse)

    def onMouse(self, event, x, y, flags, param):
        if event == cv.EVENT_MOUSEMOVE:
            self.state[0] = x
            self.state[1] = y
        if event == cv.EVENT_LBUTTONDOWN:
            self.state[2] = 1
            if self.onMouseDown is not None:
                self.onMouseDown(x, y)
        if event == cv.EVENT_LBUTTONUP:
            self.state[2] = 0


T = int(input())

for tc in range(1, T+1):
    N, M = map(int, input().split())
    arr = list()
    for _ in range(N):
        arr.append(list(map(int, input().split())))

    cost = 0   # 나무를 심는 총 비용
    cnt = 0    # 심어진 나무의 그루 수
    mx = 0     # 가장 비싼 나무의 가격
    line = 0   # 가장 비싼 나무가 심어진 열
    for i in range(N):
       for j in range(M):
            if j % 2 == 0:   # idx j % 2 == 0  -> idx[0]을 포함한 짝수열
                cost += arr[i][j]   # 금액에 그 칸의 비용을 추가
                cnt += 1    # 심은 나무의 그루 수 +1
            if j % 2 == 0 and arr[i][j] >= mx:  # 심을 칸에 해당되면서, 더 비쌀 때
                # input 값을 보니 같은 가격의 나무가 존재한다.
                mx = arr[i][j]  # 가장 비싼 나무의 가격을 재지정 해준다.
                line = j + 1    # j = idx number 이므로 열 표시를 위해서는 j+1

    print(f'#{tc} {cost} {cnt} {mx} {line}')


#A* algorithmn : finding the shortest path on graph
class Node:
    def __init__(self,parent=None,position=None):
        self.parent = parent #where it come from e.g. Node
        self.position = position #where it stay in the graph e.g (row,column)
        self.g = 0 #cost from start position to current position
        self.h = 0 #estimated cost from end to current position, a^2 + b^2 = c^2
        self.f = self.g + self.h #g+h = total cost

def A_star_algor(maze,start,end):
    show_path = maze
    openList = [] #storing the set of nodes that is going to be evaluated
    closedList = [] #storing the set of nodes that has been evaluated (e.g. store their position)
    startNode = Node(None,start) #prepare for the start position

    openList.append(startNode)
    while len(openList)>0:
        #find the currentNode which is the one with the LOWEST f cost
        currentNode = openList[0]
        currentNode_index = 0
        for index,node in enumerate(openList):
            if node.f < currentNode.f:
                currentNode = node
                currentNode_index = index

        #remove currentNode from openList and add it to the closedList which indicates that it has been CHOSEN before
        openList.pop(currentNode_index)
        closedList.append(currentNode.position)

        #if currentNode == endNode(destination), end the finding and show and reverse the path
        if currentNode.position == end:
            show_path[currentNode.position[0]][currentNode.position[1]] = 6
            while currentNode.parent != None:
                currentNode = currentNode.parent
                show_path[currentNode.position[0]][currentNode.position[1]] = 6
            return show_path
        #prepare the moving directions to all neighbours
        directions = ((0,-1),(0,1),(-1,0),(1,0),(-1,-1),(1,1),(-1,1),(1,-1))
        #for each neighbour of currentNode
        for direction in directions:
            #if it is not walkable(e.g. out of range/wall), try next direction
            if currentNode.position[0]+direction[0]<0 or currentNode.position[0]+direction[0]>=len(maze) \
                or currentNode.position[1]+direction[1]<0 or currentNode.position[1]+direction[1]>=len(maze[0]):
                continue
            elif maze[currentNode.position[0]+direction[0]][currentNode.position[1]+direction[1]] != 0:
                continue

            #if it is in closedList, try next
            if (currentNode.position[0]+direction[0],currentNode.position[1]+direction[1]) in closedList:
                continue
            #if it is valid, do something
            neighbour = Node(currentNode,(currentNode.position[0]+direction[0],currentNode.position[1]+direction[1]))
            neighbour.g = currentNode.g + 1 #you can have another methods for calculating it
            neighbour.h = (neighbour.position[1]-end[1])**2+(neighbour.position[0]-end[0])**2
            in_openList = False
            for index,open_Node in enumerate(openList): #check if it is already in the openList, if so, do something
                if neighbour.position == open_Node.position:
                    in_openList = True
                    if neighbour.g < open_Node.g: #if it is better than previous path(based on g cost)
                        openList[index] = neighbour # replace the one with a better path

            if not in_openList:
                openList.append(neighbour)

if __name__ == '__main__':
    maze = ([0,1,0,0,0], #0 for walkable 1 for unwalkable e.g. wall
            [0,0,1,0,0],
            [0,0,0,1,0],
            [0,0,0,1,0],
            [0,0,0,0,0])
    start = (0,0)
    end = (3,4)
    result_path = A_star_algor(maze,start,end)
    for row in result_path:
        for column in row:
            print(column,end=' ')
        print()


#!/usr/bin/env python3
"""
    Insertion sort is based on the idea that one element from the input elements is
    consumed in each iteration to find its correct position i.e, the position to which
    it belongs in a sorted array.
"""

def insertion_sort(arr):
    """
    Insertion Sort
    Complexity: O(n^2)
    """

    def swap(i, j):
        arr[i], arr[j] = (arr[j], arr[i])

    # Scan the entire array doing the insertion sort
    for arr_ptr in range(len(arr)):
        curr_pos = arr_ptr

        # Keep swapping values that are greater than the current item and later save the
        # position where the swapping occurred
        while (curr_pos > 0) and (arr[curr_pos - 1] > arr[curr_pos]):
            # Swap the current item down the list
            swap(curr_pos - 1, curr_pos)
            curr_pos -= 1  # Reduce the current position.

    return arr

if __name__ == "__main__":
    alist = [54, 26, 93, 17, 17, 77, 102, 54, 31, 44, 55, 20]
    print(insertion_sort(alist))


import requests
import pickle
from datetime import datetime
import pandas as pd

def load_model(filename):
    with open(filename, 'rb') as file:
        model = pickle.load(file)

    return model

def is_holiday(date):
    endpoint = "https://date.nager.at/Api/v2/IsPublicHoliday/{year}-{month}-{day}"

    year = date.year
    month = date.month
    day = date.day

    response = requests.get(endpoint.format(year=year, month=month, day=day))

    if response.status_code == 200 and response.json() is True:
        return 1  # holiday
    else:
        return 0  # not holiday

# def get_weather_data(latitude, longitude):
#     endpoint = "https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}&hourly=relativehumidity_2m,apparent_temperature,precipitation,snowfall,surface_pressure,visibility,windspeed_10m,uv_index"
#
#     response = requests.get(endpoint.format(latitude=latitude, longitude=longitude))
#
#     if response.status_code == 200:
#         data = response.json()
#         forecast = data['hourly']
#
#         weather_data = []
#         for hour in range(24):
#             app_temp = forecast['apparent_temperature'][hour]
#             precip = forecast['precipitation'][hour]
#             pres = forecast['surface_pressure'][hour]
#             rh = forecast['relativehumidity_2m'][hour]
#             snow = forecast['snowfall'][hour]
#             uv = forecast['uv_index'][hour]
#             vis = forecast['visibility'][hour]
#             wind_spd = forecast['windspeed_10m'][hour]
#
#             weather_data.append([app_temp, precip, pres, rh, snow, uv, vis, wind_spd])
#
#         return weather_data
#     else:
#         return None

def get_weather_data(latitude, longitude):
    endpoint = "https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}&hourly=temperature_2m,relativehumidity_2m,weathercode,visibility,windspeed_80m"

    response = requests.get(endpoint.format(latitude=latitude, longitude=longitude))

    if response.status_code == 200:
        data = response.json()
        forecast = data['hourly']

        weather_data = []
        for hour in range(24):
            visibility = forecast['visibility'][hour]
            wind_speed = forecast['windspeed_80m'][hour]
            humidity = forecast['relativehumidity_2m'][hour]
            temp = forecast['temperature_2m'][hour]
            weather = forecast['weathercode'][hour]

            weather_code = {'cloudy': [45, 48], 'rain': [51, 53, 55, 56, 57, 61, 63, 65, 66, 67, 80, 81, 82, 95],
                            'sunny': [0, 1, 2, 3], 'snow': [71, 73, 75, 77, 85, 86, 96, 99]}

            main_weather = None
            for category, codes in weather_code.items():
                if weather in codes:
                    main_weather = category
                    break  # Exit the loop once the main_weather is found

            # Encode 'main_weather' column to one-hot
            cloudy = 1 if main_weather == 'cloudy' else 0
            rain = 1 if main_weather == 'rain' else 0
            snow = 1 if main_weather == 'snow' else 0
            sunny = 1 if main_weather == 'sunny' else 0

            weather_data.append({
                'temp': temp,
                'visibility': visibility,
                'wind_speed': wind_speed,
                'humidity': humidity,
                'cloudy': cloudy,
                'rain': rain,
                'snow': snow,
                'sunny': sunny
            })

        return weather_data
    else:
        return None

def make_prediction(model, data):
    # Make the prediction
    prediction = model.predict(data)
    return prediction


import collections
import heapq
# Similar as LC 0621

# Solution 1,
# Assume most common value is c and its frequency is v, then we have,
# c__c__c...__c
# so we need to fill at least (v - 1) slots, otherwise we cannot make two adjacent
# chars different, so if total length is n, then we have (n - v) chars needs to fill
# v - 1 holes, => n - v >= v - 1
class Solution(object):
    def reorganizeString(self, S):
        """
        :type S: str
        :rtype: str
        """
        if not S:
            return S

        n = len(S)
        d = collections.Counter(S)
        c, v = d.most_common(1)[0]

        if 2 * v - n - 1 > 0:
            return ''

        res = [[c] for _ in range(v)]
        res.append([])

        idx = 0
        for x in sorted(d, key=lambda x: -d[x]):
            if x != c:
                for _ in range(d[x]):
                    res[idx].append(x)
                    idx = (idx + 1) % (v + 1)

        res = ''.join(''.join(x) for x in res)

        return res

# Solution 2, priority queue solution, more elegant
class Solution(object):
    def reorganizeString(self, S):
        """
        :type S: str
        :rtype: str
        """
        d = collections.Counter(S)

        q = [[-v, c] for c, v in d.items()]

        heapq.heapify(q)
        res = []
        while len(q) > 1:
            v1, c1 = heapq.heappop(q)
            v2, c2 = heapq.heappop(q)

            res.append(c1)
            res.append(c2)

            v1 += 1
            v2 += 1

            if v1 != 0:
                heapq.heappush(q, [v1, c1])
            if v2 != 0:
                heapq.heappush(q, [v2, c2])

        if len(q) == 1 and q[0][0] < -1:
            return ''
        if len(q) == 1:
            res.append(q[0][1])

        res = ''.join(res)

        return res


# 查询北海365招聘网上的职位信息
# https://www.365zhaopin.com/
# author: kinofgl
# -*- coding: utf-8 -*-

import random
import re
import time
import csv
import requests
from bs4 import BeautifulSoup
from fake_user_agent.main import user_agent
from requests import RequestException
from dingtalkchatbot.chatbot import DingtalkChatbot, ActionCard, CardItem

class BH365Zhaopin(object):
    def __init__(self):
        self.url = 'https://www.365zhaopin.com/'
        self.headers = {'User-Agent': user_agent()}

    def get_html(self, url):
        while True:
            try:
                response = requests.get(url, headers=self.headers, timeout=10)
                response.raise_for_status()
                response.encoding = response.apparent_encoding
                return response.text
            except RequestException:
                print('网络错误，请重试')
                time.sleep(random.random() * 3)

    def get_page_num(self, html):
        while True:
            try:
                soup = BeautifulSoup(html, 'lxml')
                page_num = soup.select('span.ml20')[0].get_text()
                return int(page_num[2:5])
            except:
                return None

    def get_job_info(self, html):
        soup = BeautifulSoup(html, 'lxml')
        job_items = soup.select('div.w1024.f-yehei > div.main-ul > ul > li')
        job_info = []
        for job_item in job_items:
            job_name = job_item.find('div', class_='panl1').find('a').get_text().strip()
            job_company = job_item.find('div', class_='panl10 mt3').get_text().strip()
            job_time = job_item.find('div', class_='panl5').get_text().strip()
            job_url = self.url + job_item.find('div', class_='panl1').find('a')['href']
            job_salary = job_item.find('div', class_='panl3 salary-panl3').get_text().strip()
            if re.search(r'底薪\d{4,5}', job_salary):
                job_salary = re.search(r'(?<=底薪)\d{4,5}', job_salary).group()
            elif re.search(r'￥\d{4,5}', job_salary):
                job_salary = re.search(r'(?<=￥)\d{4,5}', job_salary).group()
            else:
                continue
            job_info.append([job_name, job_salary, job_company, job_time, job_url])
        return job_info

    def job_info_filter(self, list):
        salary_list = []
        for item in list:
            if int(item[1]) > 10000:
                if re.search(r'(助理)|(副)|(行政)|(主管)', item[0]):
                    salary_list.append(item)
        return salary_list

    def save_csv(self, job_info):
        today = time.strftime('%Y-%m-%d', time.localtime())
        filepath = 'BH365Zhaopin_' + today + '.csv'
        with open(filepath, 'a', encoding='utf-8', newline='') as f:
            writer = csv.writer(f)
            writer.writerows(job_info.values())

# 起始链接
start_page = r'https://www.365zhaopin.com/index.php?do=search&p='
# 存放职位信息的文件路径
csv_file = r'C:\Users\Michael\OneDrive\桌面\我的工作区\365job.csv'
zhapin = BH365Zhaopin()

# 解析第1页取得总页数
html = zhapin.get_html(start_page + '1')
page_num = zhapin.get_page_num(html)
print('总页数：', page_num)

my_job_info = []

# 解析第1-2页获取职位信息
for i in range(1, page_num + 1):
    html = zhapin.get_html(start_page + str(i))
    job_info = zhapin.get_job_info(html)
    job_info_filter = zhapin.job_info_filter(job_info)
    if len(job_info_filter) > 0:
        for item in job_info_filter:
            my_job_info.append(item)
    print('第', i, '/ %s 页解析完成' % page_num)
    time.sleep(random.random() * 3)

print(my_job_info)

# WebHook地址
webhook = r'https://oapi.dingtalk.com/robot/send?access_token' \
          r'=80da5c52f55d190c732e25b0d222249c2e509a29df36c78d3b389b14d211c724 '
# 机器人密钥
secret = r'SECf1d13f27bbceb66a187c37e1a4e422e87e52d7718727f3a548f9b9533b94c3c0'
# 可选：创建机器人勾选“加签”选项时使用

# 初始化机器人小丁
xiaoding = DingtalkChatbot(webhook, secret=secret)

xiaoding.send_markdown(title='今日天气', text=str(my_job_info), is_at_all=False)


import numpy as np
from scipy.spatial.distance import cdist
from sklearn.gaussian_process.kernels import _check_length_scale, RBF as SRBF

class RBF(SRBF):
    def __call__(self, X, Y=None, eval_gradient=False):
        if eval_gradient and Y is not None:
            X = np.atleast_2d(X)

            length_scale = _check_length_scale(X, self.length_scale)
            dists = cdist(X / length_scale, Y / length_scale, metric='sqeuclidean')

            K = np.exp(-.5 * dists)

            if self.hyperparameter_length_scale.fixed:
                return K, np.empty((X.shape[0], X.shape[0], 0))
            elif not self.anisotropic or length_scale.shape[0] == 1:
                K_gradient = (K * dists)[:, :, np.newaxis]
                return K, K_gradient
            elif self.anisotropic:
                K_gradient = (X[:, np.newaxis, :] - Y[np.newaxis, :, :]) ** 2 \
                             / (length_scale ** 2)
                K_gradient *= K[..., np.newaxis]
                return K, K_gradient

        else:
            return super().__call__(X, Y, eval_gradient)


'''Crie um programa que leia o nome e o preço de vários produtos. O programa deverá perguntar se o usuário vai continuar ou não. No final, mostre:

A) qual é o total gasto na compra.

B) quantos produtos custam mais de R$1000.

C) qual é o nome do produto mais barato.'''

from time import sleep

print('-'*60)
print(f'{"LOJA TÁ BARATO DEMAIS":^60}')
print('-'*60)
total = cont = mais_barato = mais_de_1000 = 0
barato = ' '
while True:
    nome = str(input('Nome do produto: '))
    valor = float(input('Valor:R$ '))
    total += valor
    cont += 1
    print()
    escolha = ' '
    while escolha not in 'SN':
        escolha = str(input('Deseja passar mais algum produto? [S/N]: ')).strip().upper()[0]
        if escolha not in 'SN':
            print()
            print('ERRO: Digite apenas Sim ou não')
            print()
    print()
    if valor > 1000:
        mais_de_1000 += 1
    if cont == 1 or valor < mais_barato:
        mais_barato = valor
        barato = nome
    if escolha == 'N':
        break
print(f'''O total gasto na compra foi de R${total}
O número de produtos com valor acima de R$1000 foi de {mais_de_1000:.2f}
E o nome do produto mais barato é {barato} e o valor foi de R${mais_barato:.2f}''')

Curso em Vídeo/Python/Exercicios/Laço de repetição While/Loja v2.0.py


import abc
import logging

from decimal import Decimal, ROUND_HALF_UP

# represents a block (an input, filter, or output) in a data flow diagram
class Block(object):
    __metaclass__ = abc.ABCMeta

    #
    # Block device types that map to physical sensors.
    #
    SENSOR_DEVICE_TYPES = [ "temperature",
                            "humidity",
                            "light",
                            "soilmoisture",
                            "CO2" ]

    # create a block using a block spec dictionary
    def __init__(self, block_spec=None):
        if block_spec is not None:
            self.id = block_spec['id']
            self.name = block_spec['name']
            self.type = block_spec['type']
            self.source_ids = block_spec['sources']
            self.required_source_count = block_spec['input_count']

            #
            # Do not set value from the spec for actual sensors which
            # might not be connected and therefore should not return
            # a value.
            #
            if self.type not in self.SENSOR_DEVICE_TYPES:
                #
                # For non device types (like numeric blocks) set the
                # value from the spec.
                #
                self.value = block_spec.get('value', None)
            else:
                self.value = None

            self.params = block_spec.get('params', {})
            self.input_type = block_spec['input_type']
            self.output_type = block_spec['output_type']
            self.decimal_places = block_spec.get('decimal_places', None)
            if self.value is not None and (not self.output_type == 'i'):  # if not image
                self.decimal_places = self.compute_decimal_places(self.value)
                self.value = float(self.value)  # fix(later): handle non-numeric types?
            self.sources = []
            self.dest_ids = []
            self.stale = True

    def is_numeric(self):
        return not self.output_type == 'i'

    # compute the value of this block, based on the values of the current input blocks and user-specified parameters
    # implemented in sub-class if needed
    def compute(self, inputs, params):
        return None

    def get_source_values(self):
        source_values = []
        self.decimal_places = 0
        for source in self.sources:

            # logging.debug("%s Checking source %s" % (self.name, source))

            if source.stale:
                # logging.debug("%s Source is stale. Updating..." % (self.name))
                source.update()
            if source.value is not None:
                # logging.debug("%s Appending %s..." % (self.name, source.value))
                if source.decimal_places > self.decimal_places:
                    self.decimal_places = source.decimal_places
                source_values.append(source.value)
        return source_values

    def compute_value(self, source_values):
        source_values_length = len(source_values)
        if source_values_length > 0 and source_values_length >= self.required_source_count:
            self.value = self.compute(source_values, self.params)
            if self.is_numeric() and self.value is not None:
                self.value = round(self.value, self.decimal_places)
        else:
            self.value = None

    def round(self, value, decimal_places):
        # Convert decimal places, so quanitize can be used for accurate rounding
        # 6 decimal places -> .000001 = decimal_exp
        # 2 decimal places -> .01 = decimal_exp
        decimal_exp = Decimal(10) ** (-1 * decimal_places)
        return float(Decimal(str(value)).quantize(decimal_exp, rounding=ROUND_HALF_UP))

    # compute a new value for this block (assuming it has inputs/sources)
    def update(self):
        # we can only internally update blocks that have sources; others must be updated from the outside

        # logging.debug("Block update() %s %s" %
        #                (self.name, self.get_source_values()))

        if self.required_source_count:

            # logging.debug("Block update() checking sources")

            # get all defined source values
            source_values = self.get_source_values()

            # compute new value for this block
            self.compute_value(source_values)

        # logging.debug("Block update() %s value %s" %
        #                (self.name, self.value))

        # mark the block as non-stale, since we've updated the value or determined that no update is needed
        self.stale = False

    # compute the number of decimal places present in a string
    # representation of a number.
    # examples: "1e-11" = 11, "10.0001" = 4
    def compute_decimal_places(self, num_str):
        return abs(Decimal(str(num_str)).as_tuple().exponent)

    # a helper function for reading from a list of parameters
    def read_param(self, params, name, default=None):
        if params is not None:
            param = self.read_param_obj(params, name)
            if param:
                return param['value']
        return default

    def read_param_obj(self, params, name):
        for param in params:
            if param['name'] == name:
                return param
        return None