import numpy
from collections import defaultdict

def epsilon_greedy_policy(env, S, Q, epsilon):
    """Act epsilon greedily with respect to action-value funtion Q in state S.

    env is an OpenAI gym environment.
    S is state where the agent is.
    Q is action-value function.
    epsilon is probability of taking random action.
    """
    if numpy.random.rand() < epsilon:
        return env.action_space.sample()
    # else choose action which maximize Q in S
    return numpy.argmax([Q[S, A] for A in range(env.action_space.n)])

def sarsa(env, n_episodes, gamma=1.0, alpha=0.5, epsilon=0.1):
    """Sarsa algorithm.

    Return action-value function for optimal epsilon-greedy policy for an
    environment.

    env is an OpenAI gym environment.
    n_episodes is number of episodes to run.
    gamma is an discount factor.
    alpha is an learning rate.
    epsilon is probability of selecting random action.
    """
    # rather than store Q as table use dictionary (default value is 0)
    Q = defaultdict(float)
    for _ in range(n_episodes):
        # reset environment
        S = env.reset()
        # choose epsilon-greedy action with respect to Q
        A = epsilon_greedy_policy(env, S, Q, epsilon)
        while True:
            S_prime, R, done, _ = env.step(A)
            A_prime = epsilon_greedy_policy(env, S_prime, Q, epsilon)
            # temporal-difference update
            Q[S, A] += alpha * (R + gamma * Q[S_prime, A_prime] - Q[S, A])
            S, A = S_prime, A_prime
            if done:
                break
    return Q

def q_learning(env, n_episodes, gamma=1.0, alpha=0.5, epsilon=0.1):
    """Q-learning algorithm.

    Return optimal action value function Q. It is off-policy
    temporal-difference method.

    env is an OpenAI gym environment.
    n_episodes is number of episodes to run.
    gamma is an discount factor.
    alpha is an learning rate.
    epsilon is probability of selecting random action.
    """
    # rather than store Q as table use dictionary (default value is 0)
    Q = defaultdict(float)
    for _ in range(n_episodes):
        S = env.reset()
        while True:
            # select epsilon-greedy action
            A = epsilon_greedy_policy(env, S, Q, epsilon)
            S_prime, R, done, _ = env.step(A)
            # Q update
            max_Q = numpy.max(
                    [Q[S_prime, A] for A in range(env.action_space.n)]
                    )
            Q[S, A] += alpha * (R + gamma * max_Q - Q[S, A])
            S = S_prime
            if done:
                break
    return Q

def get_policy(env, Q):
    """Return greedy policy with respect to action-value function Q.

    env is an OpenAI environment.
    Q is action-value function.
    """
    policy = numpy.zeros((env.height, env.width), numpy.int)
    for i in range(env.height):
        for j in range(env.width):
            S = i, j
            policy[S] = numpy.argmax(
                    [Q[S, A] for A in range(env.action_space.n)]
                    )
    return policy


# clustering_legacy.py
# Hang Su 2017
# Usage: see python clustering_legacy.py -h

import argparse
import numpy as np
from utils import TimedBlock, load_ndarray, save_ndarray, DisjointSet

def constraints_from_matrix(mat, target_fn=(lambda v: v)):
    """Convert constrain format from matrix representation to set of pairs."""
    constraint_pairs = set()
    if mat is None:
        return constraint_pairs
    for r in range(mat.shape[0]):
        constraint_pairs.update(filter(lambda p: target_fn(mat[p[0], p[1]]), ((r, c) for c in range(r+1, mat.shape[0]))))
    return constraint_pairs

def vector_cluster_repr(clusters, num_samples, start_idx=0, check_completeness=True, dtype=np.int32):
    """Convert cluster format from set of clusters to a vector containing cluster id for each data point."""
    vec = np.zeros(num_samples, dtype=dtype)
    seen = set()
    for i, c in zip(range(start_idx, len(clusters) + start_idx), list(clusters)):
        vec[list(c)] = i
        if check_completeness:
            seen.update(c)
    if check_completeness and len(seen) != num_samples:
        print('Warning: clusters do not cover all the nodes.')
    return vec

def constraint_similarity_clustering(similarity, neg_constraints, threshold=None, num_clusters=None):
    """Clustering w/ do-not-connect constraints.

    :param similarity: an np matrix (float32) storing the pairwise similarity between nodes
    :param neg_constraints: a set of negative constraints as 2-tuples
    :param threshold: pairs with similarity lower than threshold will not be connected
    :param num_clusters: the wanted number of clusters; not that one of threshold and num_clusters need to be None
    :return: a list of clusters, each contains its members in a list; or a list of such lists if num_clusters=0
    """
    if (threshold is None) + (num_clusters is None) != 1:
        raise ValueError('One and only one of threshold and num_clusters should be specified.')

    num_samples = similarity.shape[0]

    # use disjoint-set data structure to maintain the clusters
    clusters = DisjointSet(num_samples, neg_constraints)

    if threshold is not None:
        # construct tuples (i, j, sim) for the pairs in the upper right triangle that meet similarity threshold
        similarity_of_pairs = [(r, c, similarity[r, c])
                               for r in range(num_samples-1)
                               for c in range(r+1, num_samples)
                               if similarity[r, c] >= threshold]

        # sort the pairs according to similarity (from high to low)
        similarity_of_pairs.sort(key=lambda v: v[2], reverse=True)

        # iterate through pairs, update clusters (when not violating any do-not-connect constraints)
        for p in similarity_of_pairs:
            clusters.union(p[0], p[1])

        return clusters.get_clusters()
    elif num_clusters > 0:
        if num_clusters > num_samples:
            print('Warning: {} clusters can not be found on {} samples.'.format(num_clusters, num_samples))

        # construct tuples (i, j, sim) for all pairs in the upper right triangle
        similarity_of_pairs = [(r, c, similarity[r, c])
                               for r in range(num_samples-1)
                               for c in range(r+1, num_samples)]

        # sort the pairs according to similarity (from high to low)
        similarity_of_pairs.sort(key=lambda v: v[2], reverse=True)

        # iterate through pairs, update clusters (when not violating any do-not-connect constraints)
        cur_num_clusters = num_samples
        for p in similarity_of_pairs:
            if cur_num_clusters <= num_clusters:
                break
            cur_num_clusters -= clusters.union(p[0], p[1])
        if cur_num_clusters > num_clusters:
            print('Warning: cannot get {} clusters, got {} instead.'.format(num_clusters, cur_num_clusters))

        return clusters.get_clusters()
    else:
        # construct tuples (i, j, sim) for all pairs in the upper right triangle
        similarity_of_pairs = [(r, c, similarity[r, c])
                               for r in range(num_samples-1)
                               for c in range(r+1, num_samples)]

        # sort the pairs according to similarity (from high to low)
        similarity_of_pairs.sort(key=lambda v: v[2], reverse=True)

        # iterate through pairs, update clusters (when not violating any do-not-connect constraints)
        clusters_hierarchy = [clusters.get_clusters()]
        for p in similarity_of_pairs:
            if clusters.union(p[0], p[1]):
                clusters_hierarchy.append(clusters.get_clusters())

        return clusters_hierarchy

def main():
    parser = argparse.ArgumentParser(description='Constraint Similarity-Based Clustering.')
    parser.add_argument('similarity', type=str, help='Path to a file containing similarity matrix')
    parser.add_argument('output', type=str, help='Output file path')
    parser.add_argument('threshold', type=float, help='Threshold, or the number of clusters when -n is turned on')
    parser.add_argument('-c', '--constraints', type=str, help='Path to a file containing constraints')
    parser.add_argument('-z', '--zero-based', action='store_true', help='Cluster ID will start from 0 if turned on')
    parser.add_argument('-d', '--distance', action='store_true', help='Distance is given rather than similarity')
    parser.add_argument('-n', '--num-clusters', action='store_true', help='Number of clusters should be given if True')
    parser.add_argument('-v', '--verbose', action='store_true', help='Output runtime information when True')
    args = parser.parse_args()

    # load similarity matrix
    with TimedBlock('Loading similarity matrix from {}'.format(args.similarity), verbose=args.verbose):
        similarity = load_ndarray(args.similarity)
    if args.distance:
        similarity *= -1
        if not args.num_clusters:
            args.threshold *= -1

    # load negative constraints (do-not-link constraints)
    if args.constraints:
        with TimedBlock('Loading constraints from {}'.format(args.constraints), verbose=args.verbose):
            constraints = load_ndarray(args.constraints, dtype=np.bool)
        with TimedBlock('Converting constraints', verbose=args.verbose):
            neg_constraints = constraints_from_matrix(constraints)
    else:
        neg_constraints = None

    # compute clusters
    (threshold, num_clusters) = (None, int(args.threshold)) if args.num_clusters else (args.threshold, None)
    with TimedBlock('Computing clusters', verbose=args.verbose):
        clusters = constraint_similarity_clustering(similarity, neg_constraints, threshold, num_clusters)

    # save results
    with TimedBlock('Converting clusters', verbose=args.verbose):
        if isinstance(clusters[0][0], list):
            cluster_hierarchy = clusters
            clusters = np.zeros((len(clusters), similarity.shape[0]), dtype=np.int32)
            for i, c in enumerate(cluster_hierarchy):
                clusters[i] = vector_cluster_repr(c, similarity.shape[0], start_idx=(0 if args.zero_based else 1))
        else:
            clusters = vector_cluster_repr(clusters, similarity.shape[0], start_idx=(0 if args.zero_based else 1))
    with TimedBlock('Saving results to {}'.format(args.output), verbose=args.verbose):
        save_ndarray(args.output, clusters, var_name='clusters')

if __name__ == '__main__':
    main()


import pytest
from ezdxf.lldxf.tagger import internal_tag_compiler
from ezdxf.document import Drawing
from ezdxf import DXFValueError, decode_base64

def test_dxfversion_1():
    doc = Drawing.from_tags(internal_tag_compiler(TEST_HEADER))
    assert "AC1009" == doc.dxfversion

@pytest.fixture(scope="module")
def dwg_r12():
    return Drawing.new("AC1009")

def test_dxfversion_2(dwg_r12):
    assert "AC1009" == dwg_r12.dxfversion

def test_acad_release(dwg_r12):
    assert "R12" == dwg_r12.acad_release

def test_get_layer(dwg_r12):
    layer = dwg_r12.layers.get("0")
    assert "0" == layer.dxf.name

def test_error_getting_not_existing_layer(dwg_r12):
    with pytest.raises(DXFValueError):
        layer = dwg_r12.layers.get("TEST_NOT_EXISTING_LAYER")

def test_create_layer(dwg_r12):
    layer = dwg_r12.layers.new("TEST_NEW_LAYER")
    assert "TEST_NEW_LAYER" == layer.dxf.name

def test_error_adding_existing_layer(dwg_r12):
    with pytest.raises(DXFValueError):
        layer = dwg_r12.layers.new("0")

def test_has_layer(dwg_r12):
    assert "0" in dwg_r12.layers

def test_has_not_layer(dwg_r12):
    assert "TEST_LAYER_NOT_EXISTS" not in dwg_r12.layers

def test_removing_layer(dwg_r12):
    dwg_r12.layers.new("TEST_NEW_LAYER_2")
    assert "TEST_NEW_LAYER_2" in dwg_r12.layers
    dwg_r12.layers.remove("TEST_NEW_LAYER_2")
    assert "TEST_NEW_LAYER_2" not in dwg_r12.layers

def test_error_removing_not_existing_layer(dwg_r12):
    with pytest.raises(DXFValueError):
        dwg_r12.layers.remove("TEST_LAYER_NOT_EXISTS")

@pytest.fixture(scope="module")
def dwg_r2000():
    return Drawing.new("AC1015")

def test_r2000_dxfversion(dwg_r2000):
    assert "AC1015" == dwg_r2000.dxfversion

def test_r2000_acad_release(dwg_r2000):
    assert "R2000" == dwg_r2000.acad_release

@pytest.fixture
def min_r12():
    return Drawing.from_tags(internal_tag_compiler(MINIMALISTIC_DXF12))

def test_min_r12_header_section(min_r12):
    assert hasattr(min_r12, "header")
    assert min_r12.header["$ACADVER"] == "AC1009"
    assert min_r12.header["$DWGCODEPAGE"] == "ANSI_1252"

def test_min_r12_layers_table(min_r12):
    assert hasattr(min_r12, "layers")
    assert len(min_r12.layers) == 2
    assert "0" in min_r12.layers
    assert "Defpoints" in min_r12.layers

def test_min_r12_styles_table(min_r12):
    assert hasattr(min_r12, "styles")
    assert len(min_r12.styles) == 1
    assert "Standard" in min_r12.styles

def test_min_r12_linetypes_table(min_r12):
    assert hasattr(min_r12, "linetypes")
    assert len(min_r12.linetypes) == 3
    assert "continuous" in min_r12.linetypes
    assert "ByLayer" in min_r12.linetypes
    assert "ByBlock" in min_r12.linetypes

def test_min_r12_blocks_section(min_r12):
    assert hasattr(min_r12, "blocks")
    assert len(min_r12.blocks) == 2
    assert "*Model_Space" in min_r12.blocks
    assert "*Paper_Space" in min_r12.blocks

def test_min_r12_entity_section(min_r12):
    assert hasattr(min_r12, "entities")
    assert len(min_r12.entities) == 0

def test_chain_layout_and_block(dwg_r12, dwg_r2000):
    for dwg in (dwg_r12, dwg_r2000):
        msp = dwg.modelspace()
        line_msp = msp.add_line((0, 0), (1, 1))
        blk = dwg.blocks.new("TEST_CHAIN")
        line_blk = blk.add_line((0, 0), (1, 1))

        handles = list(e.dxf.handle for e in dwg.chain_layouts_and_blocks())
        # check for unique handles
        assert len(handles) == len(set(handles))

        check = {line_msp.dxf.handle, line_blk.dxf.handle}
        assert check.intersection(handles) == check

def test_base64_encoding_r12(dwg_r12):
    data = dwg_r12.encode_base64()
    doc = decode_base64(data)
    assert doc.acad_release == "R12"

def test_base64_encoding_r2000(dwg_r2000):
    data = dwg_r2000.encode_base64()
    doc = decode_base64(data)
    assert doc.acad_release == "R2000"

def test_set_drawing_units(dwg_r12):
    dwg_r12.units = 6
    assert dwg_r12.header["$INSUNITS"] == 6
    dwg_r12.units = 5
    assert dwg_r12.header["$INSUNITS"] == 5

MINIMALISTIC_DXF12 = """  0
SECTION
  2
ENTITIES
  0
ENDSEC
  0
EOF
"""

TEST_HEADER = """  0
SECTION
  2
HEADER
  9
$ACADVER
  1
AC1009
  9
$DWGCODEPAGE
  3
ANSI_1252
  9
$HANDSEED
  5
FF
  0
ENDSEC
  0
SECTION
  2
ENTITIES
  0
ENDSEC
  0
EOF
"""

TESTCOPY = """  0
SECTION
  2
HEADER
  9
$ACADVER
  1
AC1018
  9
$DWGCODEPAGE
  3
ANSI_1252
  9
$TDUPDATE
 40
0.
  9
$HANDSEED
  5
FF
  0
ENDSEC
  0
SECTION
  2
OBJECTS
  0
ENDSEC
  0
SECTION
  2
FANTASYSECTION
  1
everything should be copied
  0
ENDSEC
  0
SECTION
  2
ALPHASECTION
  1
everything should be copied
  0
ENDSEC
  0
SECTION
  2
OMEGASECTION
  1
everything should be copied
  0
ENDSEC
  0
EOF
"""


import matplotlib.pyplot as plt
import matplotlib.animation as animation
from matplotlib import style

class PlotData:
    def __init__(self, subplot_lines, subplot_columns):
        self.fig = plt.figure()
        n = subplot_lines*subplot_columns
        self.ax = [self.fig.add_subplot(subplot_lines, subplot_columns, i+1) for i in range(n)]

        self.reset(n)

    def reset(self, subplots):
        self.x = [[[]] for _ in range(subplots)]
        self.y = [[[]] for _ in range(subplots)]
        self.data_series = [{} for _ in range(subplots)]
        self.titles = [None for _ in range(subplots)]
        self.legends = [[] for _ in range(subplots)]
        self.ylabels = [None for _ in range(subplots)]
        self.xlabels = [None for _ in range(subplots)]

    def config_subplot(self, i, title=None, legend=None, xlabel=None, ylabel=None):
        self.titles[i-1] = title
        self.legends[i-1] = legend
        self.xlabels[i-1] = xlabel
        self.ylabels[i-1] = ylabel

        if legend is not None:
            for lg in legend:
                self.data_series[i-1][lg] = len(self.data_series[i-1])
                self.x[i-1].append([])
                self.y[i-1].append([])
        else:
            self.legends[i-1] = []

    def add_data(self, subplot, series, x, y):
        if not series in self.data_series[subplot-1]:
            self.data_series[subplot-1][series] = len(self.data_series[subplot-1])
            self.x[subplot-1].append([])
            self.y[subplot-1].append([])
            self.legends[subplot-1].append(series)

        s = self.data_series[subplot-1][series]
        self.x[subplot-1][s].append(x)
        self.y[subplot-1][s].append(y)

    def plot(self):
        for i,sp in enumerate(self.ax):
            series = len(self.x[i])
            for ser in range(series):
                sp.plot(self.x[i][ser], self.y[i][ser])
            sp.grid(b=True)

            if self.titles[i] is not None:
                sp.set_title(self.titles[i])
            if self.legends[i] is not None:
                sp.legend(self.legends[i])
            if self.xlabels[i] is not None:
                sp.set_xlabel(self.xlabels[i])
            if self.ylabels[i] is not None:
                sp.set_ylabel(self.ylabels[i])


import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from pandas.plotting import scatter_matrix
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import LabelEncoder
import seaborn as sns

column_names = ['X','Y','month','day','FFMC','DMC','DC','ISI','temp','RH', 'wind', 'rain', 'area']
dataset = pd.read_csv('forestfires.csv', names=column_names)

print(dataset.head())
dataset['Log-area'] = np.log10(dataset['area']+1)
print(dataset.describe())

### Univariate plots ###
#box and whisker plots
dataset.plot(kind='box', subplots=True, layout=(5,3), sharex=False, sharey=False)
#histogram
dataset.hist(bins = 50)

fig, axs = plt.subplots(1, 2, sharey=True, tight_layout=True)

# We can set the number of bins with the `bins` kwarg

axs[0].hist(dataset['area'], bins=40)

axs[0].set_title("Area")
axs[1].hist(dataset['Log-area'], bins=40)
plt.title("Log(Area + 1)")

### Multivariate plots ###
scatter_matrix(dataset)
sns.pairplot(dataset[["Log-area", "temp", "wind", "rain"]], diag_kind="kde")
plt.show()

for i in dataset.describe().columns[:-2]:
    dataset.plot.scatter(i, 'Log-area', grid=True)

plt.show()
plt.close()


from fastapi import FastAPI
import os
import openai
from pydantic import BaseModel
from dotenv import load_dotenv

load_dotenv()
openai.api_key = os.getenv("OPENAI_API_KEY")

app = FastAPI()

class Details(BaseModel):
    report_description_url: str
    messages: list[dict[str, str]]

@app.get("/")
def root():
    return {'hello': "world"}

@app.post("/v1/assistants/response")
def assistant_response(details: Details):
    # https://www.expertmarketresearch.com/reports/detergent-grade-enzymes-market-asia-pacific

    rd_url = details.report_description_url
    messages = details.messages

    system_messages = [
        {"role": "system", "content": "You are a John."},
        {"role": "system", "content": "You are a helpful assistant."},
        {"role": "system", "content": "Be precise in answers."},
        {"role": "system", "content": f"Analyse {rd_url}"},
        {"role": "system", "content": "Competitors and key players are synonymous"},
        {"role": "system", "content": "often informing that this is only an overview."},
        {"role": "system", "content": "often informing that Complete and more Elaborate details are in full report."},
        {"role": "system", "content": "often remind full report contains more in-depth information."},
    ]
    messages = system_messages + messages
    response = openai.ChatCompletion.create(
    model="gpt-3.5-turbo",
    messages=messages,
    )

    return {
        "status": "201",
        "response": {
            "role": "assistant",
            "content": response.choices[0].message.content, # type: ignore
        }
    }


import numpy as np
from scipy import signal

# Below is a implementation of "Lucas-Kanade Optical Flow algorithm"

# input 2 images as sequence, output sparse motion field (U, V)
# window_size is the size that assume to have "convservation of pixels"
# i.e. the total strength of pixels don't change in that windows,
# which is a good approximation when scale of motion is small related to the window size.

# window_size >= 3 is better. (too large will cause computation slow)
def SparseMoField(I1, I2, window_size, tau=1e-2):

    kernel_x = np.array([[-1., 1.],
                        [-1., 1.]])
    kernel_y = np.array([[-1., -1.],
                        [1., 1.]])
    kernel_t = np.array([[1., 1.],
                         [1., 1.]])#*.25

    w = (int)(window_size/2)  # window_size is odd, all the pixels with offset in between [-w, w] are inside the window
    I1 = I1 / 255. # normalize pixels
    I2 = I2 / 255. # normalize pixels

    # for each point, calculate I_x, I_y, I_t
    mode = 'same'
    fx = signal.convolve2d(I1, kernel_x, boundary='symm', mode=mode)
    fy = signal.convolve2d(I1, kernel_y, boundary='symm', mode=mode)
    ft = signal.convolve2d(I2, kernel_t, boundary='symm', mode=mode) + \
        signal.convolve2d(I1, -kernel_t, boundary='symm', mode=mode)
    U = np.zeros(I1.shape)
    V = np.zeros(I1.shape)

    # within window window_size * window_size
    for i in range(w, I1.shape[0]-w):
        for j in range(w, I1.shape[1]-w):
            if(I1[i, j] == 1):
                Ix = fx[i-w:i+w+1, j-w:j+w+1].flatten()
                Iy = fy[i-w:i+w+1, j-w:j+w+1].flatten()
                It = ft[i-w:i+w+1, j-w:j+w+1].flatten()

                b = np.reshape(It, (It.shape[0],1)) # get b here
                A = np.vstack((Ix, Iy)).T # get A here

                # if threshold τ is larger than the smallest eigenvalue of A'A, get velocity
                if np.min(abs(np.linalg.eigvals(np.matmul(A.T, A)))) >= tau:
                    nu = np.matmul(np.linalg.pinv(A), b) # get velocity here. pinv(A) means pseudo inverse = (A'A)^(-1) A'
                    U[i,j] = nu[0]
                    V[i,j] = nu[1]

    return (U,V)

2021S - Digital Image Processing/term-project/motion-approach/sparse_motion_field.py


import atexit
import collections
import random

from Code import Books
from Code.QT import Iconos
from Code import Util
from Code import VarGen
from Code import XGestorMotor
from Code import XMotorRespuesta

ALBUMSHECHOS = "albumshechos"

class GestorMotorAlbum:
    def __init__(self, gestor, cromo):

        self.cromo = cromo

        self.gestor = gestor

        self.partida = gestor.partida

        self.nombre = cromo.nombre

        self.xirina = None
        self.xsimilar = None

        conf_motor = self.gestor.configuracion.buscaRival("irina")
        self.xirina = XGestorMotor.GestorMotor(self.gestor.procesador, conf_motor)
        self.xirina.opciones(None, 1, False)

        self.apertura = self.cromo.apertura
        if self.apertura:
            bookdef = VarGen.tbookPTZ
            self.book = Books.Libro("P", bookdef.split("/")[1], bookdef, True)
            self.book.polyglot()

        # De compatibilidad
        self.motorTiempoJugada = 0
        self.motorProfundidad = 0

        atexit.register(self.cerrar)

    def cerrar(self):
        if self.xirina:
            self.xirina.terminar()
            self.xirina = None
        if self.xsimilar:
            self.xsimilar.terminar()
            self.xsimilar = None

    def juega(self, fen):

        if self.apertura:
            pv = self.book.eligeJugadaTipo(fen, "au")
            if pv:
                self.apertura -= 1
                rmrival = XMotorRespuesta.RespuestaMotor("Apertura", "w" in fen)
                rmrival.desde = pv[:2]
                rmrival.hasta = pv[2:4]
                rmrival.coronacion = pv[4:]
                return rmrival
            else:
                self.apertura = 0

        total = self.cromo.aleatorio + self.cromo.captura + self.cromo.esquivo + self.cromo.similar + self.cromo.bien

        bola = random.randint(1, total)
        if bola <= self.cromo.aleatorio:
            return self.juega_aleatorio(fen)
        bola -= self.cromo.aleatorio
        if bola <= self.cromo.captura:
            return self.juega_captura(fen)
        bola -= self.cromo.captura
        if bola <= self.cromo.esquivo:
            return self.juega_esquivo(fen)
        bola -= self.cromo.esquivo
        if bola <= self.cromo.bien:
            return self.juega_irina(fen)
        else:
            return self.juega_similar(fen)

    def juega_aleatorio(self, fen):
        self.xirina.set_option("Personality", "Random")
        return self.run_irina(fen)

    def juega_esquivo(self, fen):
        self.xirina.set_option("Personality", "Advance")
        return self.run_irina(fen)

    def juega_captura(self, fen):
        self.xirina.set_option("Personality", "Capture")
        return self.run_irina(fen)

    def juega_irina(self, fen):
        self.xirina.set_option("Personality", "Irina")
        return self.run_irina(fen)

    def run_irina(self, fen):
        mrm = self.xirina.control(fen, 1)
        mrm.partida = self.partida
        return mrm.mejorMov()

    def juega_similar(self, fen):
        if self.xsimilar is None:
            conf_engine = self.gestor.configuracion.buscaRival(self.cromo.engine)
            self.xsimilar = XGestorMotor.GestorMotor(self.gestor.procesador, conf_engine)
            self.xsimilar.opciones(None, 5, True)
        mrm = self.xsimilar.control(fen, 5)
        mrm.partida = self.partida
        return mrm.mejorMovAjustadoSimilar(self.cromo.dif_puntos, self.cromo.mate, self.cromo.aterrizaje)

class Cromo:
    def __init__(self, clave, nombre, nivel, bien, aleatorio, captura, esquivo, similar, dif_puntos, aterrizaje, mate,
                 engine, apertura):
        self.clave = clave
        self.nombre = nombre
        self.nivel = nivel
        self.hecho = False
        self.pos = None  # se inicializa al crear el album

        # Porcentaje para seleccionar movimiento
        self.bien = bien
        self.aleatorio = aleatorio
        self.captura = captura
        self.esquivo = esquivo
        self.similar = similar

        # Para seleccionar similar en mrm con un multiPV
        self.dif_puntos = dif_puntos
        self.aterrizaje = int(aterrizaje)
        self.mate = int(mate)

        dic = {"t": "fruit", "c": "critter", "k": "komodo", "s": "stockfish"}
        self.engine = dic.get(engine, None)

        self.apertura = apertura

    def icono(self):
        return Iconos.icono(self.clave)

    def pixmap(self):
        return Iconos.pixmap(self.clave)

    def pixmap_level(self):
        li = ("Amarillo", "Naranja", "Verde", "Azul", "Magenta", "Rojo")
        return Iconos.pixmap(li[self.nivel])

class Album:
    def __init__(self, clavedb, alias):
        self.claveDB = clavedb
        self.alias = alias
        self.nombre = _F(alias)
        self.liCromos = []
        self.hecho = False
        self.ficheroDB = VarGen.configuracion.ficheroAlbumes

    def icono(self):
        return Iconos.icono(self.alias)

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

    def get_cromo(self, pos):
        return self.liCromos[pos]

    def new_cromo(self, cromo):
        cromo.siBlancas = len(self.liCromos) % 2 == 0
        self.liCromos.append(cromo)

    def get_db(self, key):
        db = Util.DicSQL(self.ficheroDB)
        resp = db[key]
        db.close()
        return resp

    def put_db(self, key, value):
        db = Util.DicSQL(self.ficheroDB)
        db[key] = value
        db.close()

    def guarda(self):
        dic = collections.OrderedDict()
        for cromo in self.liCromos:
            dic[cromo.clave] = cromo.hecho
        self.put_db(self.claveDB, dic)

    def test_finished(self):
        for cromo in self.liCromos:
            if not cromo.hecho:
                return False
        dic = self.get_db(ALBUMSHECHOS)
        if not dic:
            dic = {}
        dic[self.claveDB] = True
        self.put_db(ALBUMSHECHOS, dic)
        return True

    def reset(self):
        self.put_db(self.claveDB, None)

class Albumes:
    def __init__(self, pre_clave):
        self.ficheroDB = VarGen.configuracion.ficheroAlbumes
        self.preClave = pre_clave
        self.liGeneralCromos = self.read_csv()
        self.dicAlbumes = self.configura()

    def read_csv(self):
        return []

    def configura(self):
        return {}

    def create_album(self, alias):
        album = Album(self.preClave + "_" + alias, alias )

        for nivel, cuantos in enumerate(self.dicAlbumes[alias]):
            if cuantos:
                li = []
                for cromo in self.liGeneralCromos:
                    if cromo.nivel == nivel:
                        li.append(cromo)
                for pos, cromo in enumerate(random.sample(li, cuantos)):
                    cromo.pos = pos
                    cromo.siBlancas = pos % 2 == 0
                    cromo.hecho = False
                    album.new_cromo(cromo)
        album.guarda()
        return album

    def get_album(self, alias):
        key_db = self.preClave + "_" + alias
        dic = self.get_db(key_db)
        if dic:
            dig = {}
            for cromo in self.liGeneralCromos:
                dig[cromo.clave] = cromo
            album = Album(key_db, alias)
            li = []
            pos = 0
            for k, v in dic.iteritems():
                cromo = dig[k]
                cromo.hecho = v
                cromo.pos = pos
                cromo.siBlancas = pos % 2 == 0
                pos += 1
                li.append(cromo)
            album.liCromos = li
        else:
            album = self.create_album(alias)

        li = self.dicAlbumes.keys()
        for n, k in enumerate(li):
            if k == alias:
                album.siguiente = li[n + 1] if n < len(li) - 1 else None
                if album.siguiente:
                    dic_db = self.get_db(ALBUMSHECHOS)
                    if dic_db and dic_db.get(self.preClave + "_" + alias):
                        album.siguiente = None  # Para que no avise de que esta hecho
                break
        return album

    def reset(self, alias):
        self.create_album(alias)

    def get_db(self, key):
        db = Util.DicSQL(self.ficheroDB)
        resp = db[key]
        db.close()
        return resp

    def put_db(self, key, value):
        db = Util.DicSQL(self.ficheroDB)
        db[key] = value
        db.close()

    def list_menu(self):
        dic_db = self.get_db(ALBUMSHECHOS)
        if not dic_db:
            dic_db = {}
        dic = collections.OrderedDict()
        for uno in self.dicAlbumes:
            clave = self.preClave + "_" + uno
            dic[uno] = dic_db.get(clave, False)
        return dic

class AlbumesAnimales(Albumes):
    def __init__(self):
        Albumes.__init__(self, "animales")

        # dic = { "animales_Ant":True, "animales_Bee":True, "animales_Turtle":True, "animales_Chicken":True,
        # "animales_Eagle":True, "animales_Panda":True,
        # "animales_Hippo":True, "animales_Rabbit":True, "animales_Giraffe":True, "animales_Shark":True,
        # "animales_Wolf":True }
        # self.putDB( ALBUMSHECHOS, dic )

    def configura(self):
        dic = collections.OrderedDict()
        dic["Ant"] = (6, 0, 0, 0, 0, 0)  # 6
        dic["Bee"] = (5, 3, 0, 0, 0, 0)  # 8

        dic["Turtle"] = (4, 6, 0, 0, 0, 0)  # 10
        dic["Chicken"] = (3, 6, 3, 0, 0, 0)  # 12

        dic["Eagle"] = (3, 5, 6, 0, 0, 0)  # 14
        dic["Panda"] = (2, 4, 6, 4, 0, 0)  # 16

        dic["Hippo"] = (2, 5, 5, 6, 0, 0)  # 18
        dic["Rabbit"] = (1, 5, 5, 6, 3, 0)  # 20

        dic["Giraffe"] = (2, 5, 5, 6, 6, 0)  # 24
        dic["Shark"] = (1, 6, 6, 6, 6, 3)  # 28

        dic["Wolf"] = (2, 5, 6, 6, 6, 7)  # 32
        dic["Owl"] = (4, 6, 7, 7, 7, 9)  # 40
        return dic

    def read_csv(self):
        # x = """Animal;Nivel ;Bien;Aleatorio;Captura;Esquivo;Similar;Dif puntos;Aterrizaje;Mate;Engine;Apertura
        # Ant;0;0;100;0;0;0;1000;450;0;t;0
        # Bee;0;1;95;0;0;0;1000;450;0;k;0
        # Butterfly;0;2;90;0;0;0;1000;450;0;c;0
        # Fish;0;3;85;0;0;0;1000;450;0;s;2
        # Bat;0;5;75;0;0;0;1000;450;0;k;2
        # Bird;0;6;70;0;0;0;1000;450;0;c;2
        # Turtle;1;7;65;100;0;0;1000;450;0;s;3
        # Crab;1;8;60;95;0;0;1000;350;0;t;3
        # Duck;1;9;55;90;0;0;900;350;0;k;3
        # Chicken;1;10;50;85;0;0;900;350;0;c;3
        # Alligator;1;11;45;80;0;50;900;350;0;s;4
        # Bull;1;12;40;75;0;48;900;350;0;t;4
        # Rooster;1;14;35;70;0;46;900;350;0;k;4
        # Eagle;2;15;30;65;100;50;900;350;0;c;4
        # Crocodile;2;16;25;60;95;59;900;350;0;s;5
        # Bear;2;17;20;55;90;60;800;350;0;t;5
        # Panda;2;18;15;50;85;65;800;350;0;k;5
        # Cow;2;20;10;45;80;69;800;350;1;c;5
        # Moose;2;25;5;40;75;64;700;250;1;s;5
        # Rhino;2;30;0;35;70;63;400;250;1;t;6
        # Hippo;3;35;0;30;65;62;400;250;1;k;6
        # Rabbit;3;40;0;25;60;50;400;250;1;c;6
        # Sheep;3;45;0;20;55;55;400;250;1;s;6
        # Donkey;3;50;0;15;50;47;400;250;1;t;6
        # Pig;3;50;0;10;45;46;400;150;1;k;7
        # Deer;3;55;0;5;40;45;400;150;1;c;7
        # Frog;3;57;0;0;35;41;400;150;1;t;7
        # Giraffe;4;60;0;0;30;36;400;150;1;k;7
        # Mouse;4;61;0;0;25;39;400;150;1;c;7
        # Penguin;4;62;0;0;20;37;400;150;1;s;7
        # Snake;4;64;0;0;15;36;400;150;1;t;8
        # Shark;4;66;0;0;10;35;400;150;1;c;8
        # Turkey;4;67;0;0;10;30;400;150;1;s;8
        # Monkey;4;68;0;0;10;28;400;150;1;t;8
        # Wolf;5;70;0;0;10;26;300;150;1;k;8
        # Fox;5;72;0;0;10;24;300;150;1;c;9
        # Cat;5;74;0;0;10;22;300;150;1;s;9
        # Dog;5;75;0;0;10;20;300;150;1;t;9
        # Tiger;5;77;0;0;10;18;300;150;1;k;9
        # Lion;5;80;0;0;10;16;300;150;1;c;9
        # Horse;5;82;0;0;10;14;300;150;2;s;9
        # Elephant;5;85;0;0;10;12;300;150;2;t;9
        # Gorilla;5;90;0;0;5;10;300;150;2;k;9
        # Owl;5;100;0;0;0;0;0;150;2;c;999"""
        # p rint "        li= []"
        # for n, linea in enumerate(x.split("\n")):
        # if n:
        # animal,nivel ,bien,aleatorio,captura,esquivo,similar,dif_puntos,aterrizaje,mate,engine,
        # apertura=linea.strip().split(";")
        # p rint '        li.append(Cromo("%s",_("%s"),%s,%s,%s,%s,%s,%s,%s,%s,%s,"%s",%s))'
        # %(animal,animal,nivel,bien,aleatorio,captura,esquivo, similar,dif_puntos,aterrizaje,
        # mate,engine,apertura)

        li = [
            Cromo("Ant", _("Ant"), 0, 0, 100, 0, 0, 0, 1000, 450, 0, "t", 0),
            Cromo("Bee", _("Bee"), 0, 1, 95, 0, 0, 0, 1000, 450, 0, "k", 0),
            Cromo("Butterfly", _("Butterfly"), 0, 2, 90, 0, 0, 0, 1000, 450, 0, "c", 0),
            Cromo("Fish", _("Fish"), 0, 3, 85, 0, 0, 0, 1000, 450, 0, "s", 2),
            Cromo("Bat", _("Bat"), 0, 5, 75, 0, 0, 0, 1000, 450, 0, "k", 2),
            Cromo("Bird", _("Bird"), 0, 6, 70, 0, 0, 0, 1000, 450, 0, "c", 2),
            Cromo("Turtle", _("Turtle"), 1, 7, 65, 100, 0, 0, 1000, 450, 0, "s", 3),
            Cromo("Crab", _("Crab"), 1, 8, 60, 95, 0, 0, 1000, 350, 0, "t", 3),
            Cromo("Duck", _("Duck"), 1, 9, 55, 90, 0, 0, 900, 350, 0, "k", 3),
            Cromo("Chicken", _("Chicken"), 1, 10, 50, 85, 0, 0, 900, 350, 0, "c", 3),
            Cromo("Alligator", _("Alligator"), 1, 11, 45, 80, 0, 50, 900, 350, 0, "s", 4),
            Cromo("Bull", _("Bull"), 1, 12, 40, 75, 0, 48, 900, 350, 0, "t", 4),
            Cromo("Rooster", _("Rooster"), 1, 14, 35, 70, 0, 46, 900, 350, 0, "k", 4),
            Cromo("Eagle", _("Eagle"), 2, 15, 30, 65, 100, 50, 900, 350, 0, "c", 4),
            Cromo("Crocodile", _("Crocodile"), 2, 16, 25, 60, 95, 59, 900, 350, 0, "s", 5),
            Cromo("Bear", _("Bear"), 2, 17, 20, 55, 90, 60, 800, 350, 0, "t", 5),
            Cromo("Panda", _("Panda"), 2, 18, 15, 50, 85, 65, 800, 350, 0, "k", 5),
            Cromo("Cow", _("Cow"), 2, 20, 10, 45, 80, 69, 800, 350, 1, "c", 5),
            Cromo("Moose", _("Moose"), 2, 25, 5, 40, 75, 64, 700, 250, 1, "s", 5),
            Cromo("Rhino", _("Rhino"), 2, 30, 0, 35, 70, 63, 400, 250, 1, "t", 6),
            Cromo("Hippo", _("Hippo"), 3, 35, 0, 30, 65, 62, 400, 250, 1, "k", 6),
            Cromo("Rabbit", _("Rabbit"), 3, 40, 0, 25, 60, 50, 400, 250, 1, "c", 6),
            Cromo("Sheep", _("Sheep"), 3, 45, 0, 20, 55, 55, 400, 250, 1, "s", 6),
            Cromo("Donkey", _("Donkey"), 3, 50, 0, 15, 50, 47, 400, 250, 1, "t", 6),
            Cromo("Pig", _("Pig"), 3, 50, 0, 10, 45, 46, 400, 150, 1, "k", 7),
            Cromo("Deer", _("Deer"), 3, 55, 0, 5, 40, 45, 400, 150, 1, "c", 7),
            Cromo("Frog", _("Frog"), 3, 57, 0, 0, 35, 41, 400, 150, 1, "t", 7),
            Cromo("Giraffe", _("Giraffe"), 4, 60, 0, 0, 30, 36, 400, 150, 1, "k", 7),
            Cromo("Mouse", _("Mouse"), 4, 61, 0, 0, 25, 39, 400, 150, 1, "c", 7),
            Cromo("Penguin", _("Penguin"), 4, 62, 0, 0, 20, 37, 400, 150, 1, "s", 7),
            Cromo("Snake", _("Snake"), 4, 64, 0, 0, 15, 36, 400, 150, 1, "t", 8),
            Cromo("Shark", _("Shark"), 4, 66, 0, 0, 10, 35, 400, 150, 1, "c", 8),
            Cromo("Turkey", _("Turkeycock"), 4, 67, 0, 0, 10, 30, 400, 150, 1, "s", 8),
            Cromo("Monkey", _("Monkey"), 4, 68, 0, 0, 10, 28, 400, 150, 1, "t", 8),
            Cromo("Wolf", _("Wolf"), 5, 70, 0, 0, 10, 26, 300, 150, 1, "k", 8),
            Cromo("Fox", _("Fox"), 5, 72, 0, 0, 10, 24, 300, 150, 1, "c", 9),
            Cromo("Cat", _("Cat"), 5, 74, 0, 0, 10, 22, 300, 150, 1, "s", 9),
            Cromo("Dog", _("Dog"), 5, 75, 0, 0, 10, 20, 300, 150, 1, "t", 9),
            Cromo("Tiger", _("Tiger"), 5, 77, 0, 0, 10, 18, 300, 150, 1, "k", 9),
            Cromo("Lion", _("Lion"), 5, 80, 0, 0, 10, 16, 300, 150, 1, "c", 9),
            Cromo("Horse", _("Horse"), 5, 82, 0, 0, 10, 14, 300, 150, 2, "s", 9),
            Cromo("Elephant", _("Elephant"), 5, 85, 0, 0, 10, 12, 300, 150, 2, "t", 9),
            Cromo("Gorilla", _("Gorilla"), 5, 90, 0, 0, 5, 10, 300, 150, 2, "k", 9),
            Cromo("Owl", _("Owl"), 5, 100, 0, 0, 0, 0, 0, 150, 2, "c", 999),
        ]
        return li

class AlbumesVehicles(Albumes):
    def __init__(self):
        Albumes.__init__(self, "vehicles")

        # dic = { "animales_Ant":True, "animales_Bee":True, "animales_Turtle":True, "animales_Chicken":True,
        # "animales_Eagle":True, "animales_Panda":True,
        # "animales_Hippo":True, "animales_Rabbit":True, "animales_Giraffe":True, "animales_Shark":True,
        # "animales_Wolf":True }
        # self.putDB( ALBUMSHECHOS, dic )

    def configura(self):
        dic = collections.OrderedDict()
        dic["TouringMotorcycle"] = (4, 0, 0, 0, 0, 0)  # 4
        dic["Car"] = (3, 2, 2, 1, 0, 0)  # 8
        dic["QuadBike"] = (3, 3, 3, 3, 0, 0)  # 12
        dic["Truck"] = (4, 4, 3, 3, 2, 0)  # 16
        dic["DieselLocomotiveBoxcar"] = (4, 4, 4, 4, 4, 0)  # 20
        dic['SubwayTrain'] = (4, 5, 5, 4, 4, 2)  # 24
        dic["Airplane"] = (4, 5, 5, 5, 5, 4)  # 28
        return dic

    def read_csv(self):
        # x = """Vehicle;Nivel ;Bien;Aleatorio;Captura;Esquivo;Similar;Dif puntos;Aterrizaje;Mate;Engine;Apertura
        # Wheel;0;0;100;0;0;0;1000;450;0;t;0
        # Wheelchair;0;1;95;0;0;0;1000;450;0;k;0
        # TouringMotorcycle;0;2;90;0;0;0;1000;450;0;c;0
        # Container;0;6;70;0;0;0;1000;450;0;c;2
        # BoatEquipment;1;8;60;95;0;0;1000;350;0;t;3
        # Car;1;9;55;90;0;0;900;350;0;k;3
        # Lorry;1;9;55;90;0;0;900;350;0;k;3
        # CarTrailer;1;10;50;85;0;0;900;350;0;c;3
        # TowTruck;1;14;35;70;0;46;900;350;0;k;4
        # QuadBike;2;15;30;65;100;50;900;350;0;c;4
        # RecoveryTruck;2;16;25;60;95;59;900;350;0;s;5
        # ContainerLoader;2;17;20;55;90;60;800;350;0;t;5
        # PoliceCar;2;18;15;50;85;65;800;350;0;k;5
        # ExecutiveCar;2;30;0;35;70;63;400;250;1;t;6
        # Truck;3;35;0;30;65;62;400;250;1;k;6
        # Excavator;3;40;0;25;60;50;400;250;1;c;6
        # Cabriolet;3;45;0;20;55;55;400;250;1;s;6
        # MixerTruck;3;50;0;15;50;47;400;250;1;t;6
        # ForkliftTruckLoaded;3;55;0;10;45;46;400;150;1;k;7
        # Ambulance;4;60;0;0;30;36;400;150;1;k;7
        # DieselLocomotiveBoxcar;4;65;0;0;30;36;400;150;1;k;7
        # TractorUnit;4;70;0;0;30;36;400;150;1;k;7
        # FireTruck;4;75;0;0;20;37;400;150;1;s;7
        # CargoShip;4;76;0;0;10;35;400;150;1;c;8
        # SubwayTrain;5;85;0;0;10;20;300;150;1;t;9
        # TruckMountedCrane;5;90;0;0;10;24;300;150;1;c;9
        # AirAmbulance;5;95;0;0;10;22;300;150;1;s;9
        # Airplane;5;99;0;0;10;26;300;150;1;k;999"""
        # p rint "        li= []"
        # for n, linea in enumerate(x.split("\n")):
        # if n:
        # animal,nivel ,bien,aleatorio,captura,esquivo,similar,dif_puntos,aterrizaje,mate,engine,
        # apertura=linea.strip().split(";")
        # p rint '                    Cromo("%s",_("%s"),%s,%s,%s,%s,%s,%s,%s,%s,%s,"%s",%s))'
        # %(animal,animal,nivel,bien,aleatorio,captura,esquivo, similar,dif_puntos,aterrizaje,
        # mate,engine,apertura)

        li = [
            Cromo("Wheel", _("Wheel"), 0, 0, 100, 0, 0, 0, 1000, 450, 0, "t", 0),
            Cromo("Wheelchair", _("Wheelchair"), 0, 1, 95, 0, 0, 0, 1000, 450, 0, "k", 0),
            Cromo("TouringMotorcycle", _("TouringMotorcycle"), 0, 2, 90, 0, 0, 0, 1000, 450, 0, "c", 0),
            Cromo("Container", _("Container"), 0, 6, 70, 0, 0, 0, 1000, 450, 0, "c", 2),
            Cromo("BoatEquipment", _("BoatEquipment"), 1, 8, 60, 95, 0, 0, 1000, 350, 0, "t", 3),
            Cromo("Car", _("Car"), 1, 9, 55, 90, 0, 0, 900, 350, 0, "k", 3),
            Cromo("Lorry", _("Lorry"), 1, 9, 55, 90, 0, 0, 900, 350, 0, "k", 3),
            Cromo("CarTrailer", _("CarTrailer"), 1, 10, 50, 85, 0, 0, 900, 350, 0, "c", 3),
            Cromo("TowTruck", _("TowTruck"), 1, 14, 35, 70, 0, 46, 900, 350, 0, "k", 4),
            Cromo("QuadBike", _("QuadBike"), 2, 15, 30, 65, 100, 50, 900, 350, 0, "c", 4),
            Cromo("RecoveryTruck", _("RecoveryTruck"), 2, 16, 25, 60, 95, 59, 900, 350, 0, "s", 5),
            Cromo("ContainerLoader", _("ContainerLoader"), 2, 17, 20, 55, 90, 60, 800, 350, 0, "t", 5),
            Cromo("PoliceCar", _("PoliceCar"), 2, 18, 15, 50, 85, 65, 800, 350, 0, "k", 5),
            Cromo("ExecutiveCar", _("ExecutiveCar"), 2, 30, 0, 35, 70, 63, 400, 250, 1, "t", 6),
            Cromo("Truck", _("Truck"), 3, 35, 0, 30, 65, 62, 400, 250, 1, "k", 6),
            Cromo("Excavator", _("Excavator"), 3, 40, 0, 25, 60, 50, 400, 250, 1, "c", 6),
            Cromo("Cabriolet", _("Cabriolet"), 3, 45, 0, 20, 55, 55, 400, 250, 1, "s", 6),
            Cromo("MixerTruck", _("MixerTruck"), 3, 50, 0, 15, 50, 47, 400, 250, 1, "t", 6),
            Cromo("ForkliftTruckLoaded", _("ForkliftTruckLoaded"), 3, 55, 0, 10, 45, 46, 400, 150, 1, "k", 7),
            Cromo("Ambulance", _("Ambulance"), 4, 60, 0, 0, 30, 36, 400, 150, 1, "k", 7),
            Cromo("DieselLocomotiveBoxcar", _("DieselLocomotiveBoxcar"), 4, 65, 0, 0, 30, 36, 400, 150, 1, "k", 7),
            Cromo("TractorUnit", _("TractorUnit"), 4, 70, 0, 0, 30, 36, 400, 150, 1, "k", 7),
            Cromo("FireTruck", _("FireTruck"), 4, 75, 0, 0, 20, 37, 400, 150, 1, "s", 7),
            Cromo("CargoShip", _("CargoShip"), 4, 76, 0, 0, 10, 35, 400, 150, 1, "c", 8),
            Cromo("SubwayTrain", _("SubwayTrain"), 5, 85, 0, 0, 10, 20, 300, 150, 1, "t", 9),
            Cromo("TruckMountedCrane", _("TruckMountedCrane"), 5, 90, 0, 0, 10, 24, 300, 150, 1, "c", 9),
            Cromo("AirAmbulance", _("AirAmbulance"), 5, 95, 0, 0, 10, 22, 300, 150, 1, "s", 9),
            Cromo("Airplane", _("Airplane"), 5, 99, 0, 0, 10, 26, 300, 150, 1, "k", 999),
        ]
        return li


"""
Provides functionality to interact with the database.
"""

import os

import sqlite3
from sqlite3 import Error
import numpy as np

# Path to existing database or where the database should be created
PATH_TO_DB = os.environ.get('PATH_TO_DB')

def create_connection():
    """Creates a connection to the database or creates a
    new database if it does not exist using the default path

    Returns:
        Connection: Connection to database
    """
    return create_connection_to(path_to_db=PATH_TO_DB)

def create_connection_to(path_to_db: str):
    """Creates a connection to the database or creates a
    new database if it does not exist

    Returns:
        Connection: Connection to database
    """
    conn = None
    try:
        conn = sqlite3.connect(path_to_db)
    except Error as error:
        print(error)

    return conn

def insert_abstract(conn, db_entry_abstract):
    """Inserts an abstract into the database.

    Args:
        conn (Connection): Connection to the database
        db_entry_abstract (list): List of the abstract's attributes
    """
    sql_command = ("INSERT INTO abstract(abstract_id, year, title, "
                   "content, doctype, institution) VALUES(?,?,?,?,?,?)")
    cursor = conn.cursor()
    cursor.execute(sql_command, db_entry_abstract)
    conn.commit()

def insert_written_by(conn, abstract_id: int, author_id: int):
    """Inserts an entry into the written_by relation in the database.

    Args:
        conn (Connection): Connection to the database
        abstract_id (int): Id of the abstract
        author_id (int): Id of the author
    """
    sql_command = ("INSERT INTO written_by(abstract_id, "
                   "author_id) VALUES(?,?)")
    cursor = conn.cursor()
    cursor.execute(sql_command, (abstract_id, author_id))
    conn.commit()

def insert_has_competency(conn, author_id: int,
                          competency_id: int, status: str):
    """Inserts an entry into the has_competency relation in the database.

    Args:
        conn (Connection): Connection to the database
        author_id (int): Id of the author
        competency_id (int): Id of the competency
        status (str): Status of the competency from {denied, neutral, accepted}
    """
    sql_command = ("INSERT OR IGNORE INTO has_competency"
                   "(author_id, competency_id, status) VALUES(?,?,?)")
    cursor = conn.cursor()
    cursor.execute(sql_command, (author_id, competency_id, status))
    conn.commit()

def insert_derived_from(conn, competency_id: int,
                        abstract_id: int, relevancy: float):
    """Inserts an entry into the derived_from relation in the database.

    Args:
        conn (Connection): Connection to the database
        competency_id (int): Id of the competency
        abstract_id (int): Id of the abstract
        relevancy (float): Relevancy of the competency to the abstract
    """
    sql_command = ("INSERT INTO derived_from(competency_id, "
                   "abstract_id, relevancy) VALUES(?,?,?)")
    cursor = conn.cursor()
    cursor.execute(sql_command, (competency_id, abstract_id, relevancy))
    conn.commit()

def insert_category(conn, category_id: int, category_name: str):
    """Inserts an entry into the category relation in the database.

    Args:
        conn (Connection): Connection to the database
        category_id (int): Id of the category
        category_name (str): Name of the category
    """
    sql_command = """INSERT INTO category(category_id, name) VALUES(?,?)"""
    cursor = conn.cursor()
    cursor.execute(sql_command, (category_id, category_name))
    conn.commit()

def insert_has_category(conn, category_id: int, competency_id: int):
    """Inserts an entry into the has_category relation in the database.

    Args:
        conn (Connection): Connection to the database
        category_id (int): Id of the category
        competency_id (int): Id of the competency
    """
    sql_command = """INSERT OR IGNORE INTO has_category(category_id, competency_id)
                    VALUES(?,?)"""
    cursor = conn.cursor()
    cursor.execute(sql_command, (category_id, competency_id))
    conn.commit()

def get_author_id_by_name(conn, first_name: str, last_name: str) -> int:
    """Returns the id of an author by its name or creates an id if the author's
    id has not been created yet.

    Args:
        conn (Connection): Connection to the database
        first_name (str): First name of the author
        last_name (str): Last name of the author

    Returns:
        int: Id of the author
    """
    sql_get_author_id = """SELECT author_id
                           FROM author
                           WHERE first_name = ? AND last_name = ?;"""
    sql_insert_author = """INSERT INTO author(first_name, last_name)
    VALUES(?,?)"""
    cursor = conn.cursor()
    cursor.execute(sql_get_author_id, (first_name, last_name))
    result = cursor.fetchone()
    if result is None:
        # author not in db -> needs to be created
        author_id = cursor.execute(sql_insert_author,
                                   (first_name, last_name)).lastrowid
    else:
        # fetchone returns tuple, we want only the author_id
        author_id = result[0]

    conn.commit()
    return author_id

def add_category(conn, competency_name: str) -> int:
    """Adds an entry to the category relation in the database.

    Args:
        conn (Connection): Connection to the database
        competency_name (str): Name of the competency

    Returns:
        int: Id of the competency
    """
    sql_get_competency_id = """SELECT competency_id
                               FROM competency
                               WHERE competency_name = ?"""
    sql_insert_competency = """INSERT INTO competency(competency_name)
                               VALUES(?)"""
    cursor = conn.cursor()
    cursor.execute(sql_get_competency_id, (competency_name,))
    result = cursor.fetchone()
    if result is None:
        # Competency not in db -> needs to be created
        competency_id = cursor.execute(sql_insert_competency,
                                       (competency_name,)).lastrowid
    else:
        # Fetchone returns tuple, we want only the author_id
        competency_id = result[0]

    conn.commit()
    return competency_id

def get_all_categories(conn) -> list[int, str]:
    """Returns all entries in the category relation in the database.

    Args:
        conn (Connection): Connection to the database

    Returns:
        list: list[category_id, name]
    """
    sql_get_categories = """SELECT * FROM category;"""
    cursor = conn.cursor()
    cursor.execute(sql_get_categories)
    result = cursor.fetchall()
    if result is None:
        return """Something went wrong. Result for the query to fetch
    all entries of the category relation is None."""
    conn.commit()
    return result

def get_all_competencies(conn) -> list[int, str]:
    """Returns all entries in the competency relation in the database.

    Args:
        conn (Connection): Connection to the database

    Returns:
        list: list[competency_id, competency_name]
    """
    sql_get_categories = """SELECT * FROM competency;"""
    cursor = conn.cursor()
    cursor.execute(sql_get_categories)
    result = cursor.fetchall()
    if result is None:
        return 'Something went wrong.'
    conn.commit()
    return result

def get_first_available_abstract_id(conn) -> int:
    """Returns next available abstract_id meaning highest_abstract_id + 1.
    Ignoring if some abstracts have been deleted in between, so potential
    for optimization.

    Args:
        conn (Connection): Connection to the database

    Returns:
        int: next abstract id
    """
    sql_get_highest_abstract_id = """SELECT MAX(abstract_id)
                                     FROM abstract
                                  """
    cursor = conn.cursor()
    cursor.execute(sql_get_highest_abstract_id)
    highest_abstract_id = cursor.fetchone()
    if highest_abstract_id[0] is None:
        highest_abstract_id = 0
    else:
        highest_abstract_id = highest_abstract_id[0]
    next_available = highest_abstract_id + 1
    conn.commit()
    return next_available

def get_or_generate_competency_id_by_name(conn, competency_name: str) -> int:
    """Returns the id of a competency by its name or creates an id if the
    competency's id has not been created yet.

    Args:
        conn (Connection): Connection to the database
        competency_name (str): Name of the competency

    Returns:
        int: Id of the competency
    """
    sql_get_competency_id = """SELECT competency_id
                               FROM competency
                               WHERE competency_name = ?"""
    sql_insert_competency = """INSERT INTO competency(competency_name)
                               VALUES(?)"""
    cursor = conn.cursor()
    cursor.execute(sql_get_competency_id, (competency_name,))
    result = cursor.fetchone()
    if result is None:
        # competency not in db -> needs to be created
        competency_id = cursor.execute(sql_insert_competency,
                                       (competency_name,)).lastrowid
        print("Wurde hinzugefügt mit id" + str(competency_id))
    else:
        competency_id = result[0]

    conn.commit()
    return competency_id

def get_competency_id_by_name(conn, competency_id) -> int:
    """Returns the id of a competency by its name.

    Args:
        conn (Connection): Connection to the database
        competency_id (int): Id of the competency

    Returns:
        int: Id of the competency
    """
    sql_get_competency_id = """SELECT competency_id
                            FROM competency
                            WHERE competency_name = ?"""
    cursor = conn.cursor()
    cursor.execute(sql_get_competency_id, (competency_id,))
    competency_id = cursor.fetchone()
    conn.commit()
    return competency_id

def get_competency_name_by_id(conn, competency_id) -> str:
    """Returns the name of a competency by its id.

    Args:
        conn (Connection): Connection to the database
        competency_id (int): Id of the competency

    Returns:
        str: Name of the competency
    """
    sql_get_competency_id = """SELECT competency_name
                            FROM competency
                            WHERE competency_id = ?"""
    cursor = conn.cursor()
    cursor.execute(sql_get_competency_id, (competency_id,))
    competeny_name = cursor.fetchone()
    return competeny_name

def get_category_name_by_id(conn, category_id: int) -> str:
    """Returns the name of a category by its id.

    Args:
        conn (Connection): Connection to the database
        category_id (int): Id of the category

    Returns:
        str: Name of the category
    """
    sql_command = """SELECT name
                     FROM category
                     WHERE category_id = ?"""
    cursor = conn.cursor()
    cursor.execute(sql_command, (category_id,))
    category_name = cursor.fetchone()
    return category_name

def get_competencies_by_category(conn, category_name: str) -> list[int, str]:
    """Returns all competencies for a given category.

    Args:
        conn (Connection): Connection to the database
        category (str): Name of the category

    Returns:
        list: list[competency_name]
    """
    sql_get_competencies = """SELECT comp.competency_name FROM competency comp
                              JOIN has_category hc ON comp.competency_id
                              = hc.competency_id JOIN category cat ON
                              hc.category_id = cat.category_id
                              WHERE cat.name = ?;"""
    cursor = conn.cursor()
    cursor.execute(sql_get_competencies, (category_name,))
    result = cursor.fetchall()
    if result is None:
        return 'There are no competencies for this category.'
    conn.commit()
    return result

def get_competencies_by_category_id(conn, category_id: int) -> list[int, str]:
    """Returns all competencies for a given category.

    Args:
        conn (Connection): Connection to the database
        category_id (int): Id of the category

    Returns:
        list: list[competency_id, competency_name]
    """
    sql_get_competencies = """SELECT comp.competency_id, comp.competency_name
                              FROM competency comp
                              JOIN has_category hc ON comp.competency_id
                              = hc.competency_id
                              WHERE hc.category_id = ?;"""
    cursor = conn.cursor()
    cursor.execute(sql_get_competencies, (category_id,))
    result = cursor.fetchall()
    if result is None:
        return 'There are no competencies for this category.'
    conn.commit()
    return result

def get_competencies_by_author_id(conn, author_id: int) -> list[int, str]:
    """Returns all competencies for a given author.

    Args:
        conn (Connection): Connection to the database
        author_id (int): Id of the author

    Returns:
        list: list[competency_id, competency_name, status]
    """
    sql_get_competencies = """SELECT hc.competency_id, comp.competency_name,
                              hc.status FROM has_competency hc
                              JOIN competency comp ON
                              comp.competency_id = hc.competency_id
                              WHERE hc.author_id = ?;"""
    cursor = conn.cursor()
    cursor.execute(sql_get_competencies, (author_id,))
    result = cursor.fetchall()
    if result is None:
        return 'There are no competencies for this author.'
    conn.commit()
    return result

def get_competencies_by_abstract_id(conn, abstract_id: int) -> list[int, str]:
    """Returns all competencies for a given abstract.

    Args:
        conn (Connection): Connection to the database
        abstract_id (int): Id of the abstract

    Returns:
        list: List[competency_id, competency_name, relevancy]
    """
    sql_get_competencies = """SELECT df.competency_id, comp.competency_name,
                              df.relevancy FROM derived_from df
                              JOIN competency comp ON
                              comp.competency_id = df.competency_id
                              WHERE df.abstract_id = ?;"""
    cursor = conn.cursor()
    cursor.execute(sql_get_competencies, (abstract_id,))
    result = cursor.fetchall()
    if result is None:
        return 'There are no competencies for this author.'
    conn.commit()
    return result

def get_abstract_by_id(conn,
                       abstract_id: int) -> list[int, int, str, str, str, str]:
    """Returns an abstract (consisting of all its attributes) by its id.

    Args:
        conn (Connection): Connection to the database
        abstract_id (int): Id of the abstract

    Returns:
        list: List[abstract_id, year, title, content, doctype, institution]
    """
    sql_get_abstract = """SELECT * FROM abstract
                          WHERE abstract_id = ?;"""
    cursor = conn.cursor()
    cursor.execute(sql_get_abstract, (abstract_id,))
    result = cursor.fetchone()
    if result is None:
        return 'There exists no abstract with the given id.'
    conn.commit()
    return result

def get_authors_by_abstract(conn, abstract_id: int) -> list[int, str, str]:
    """Returns all authors of a given abstract.

    Args:
        conn (Connection): Connection to the database
        abstract_id (int): Id of the abstract

    Returns:
        list: List[author_id, first_name, last_name]
    """
    sql_get_abstract = """SELECT auth.author_id, auth.first_name,
                          auth.last_name FROM abstract abs
                          JOIN written_by wb
                          ON wb.abstract_id = abs.abstract_id
                          JOIN author auth ON wb.author_id = auth.author_id
                          WHERE abs.abstract_id = ?;"""
    cursor = conn.cursor()
    cursor.execute(sql_get_abstract, (abstract_id,))
    result = cursor.fetchall()
    if result is None:
        return 'There exists no author with the given abstract id.'
    conn.commit()
    return result

def get_authors_with_competency(conn,
                                competency: str) -> list[
                                    int, str, str, int, str]:
    """Returns all authors with a given competency and the status of the
    competency.

    Args:
        conn (Connection): Connection to the database
        competency_name (str): Name of the competency

    Returns:
        list: list[author_id, first_name, last_name, relevancy, status]
    """
    sql_get_authors = """SELECT auth.author_id, auth.first_name,
                         auth.last_name,
                         df.relevancy, hc.status
                         FROM author auth JOIN has_competency hc
                         ON auth.author_id = hc.author_id JOIN competency comp
                         ON hc.competency_id = comp.competency_id JOIN
                         derived_from df
                         ON comp.competency_id = df.competency_id
                         WHERE comp.competency_name = ?;"""
    cursor = conn.cursor()
    cursor.execute(sql_get_authors, (competency,))
    result = cursor.fetchall()
    if result is None:
        return 'There are no people with this competency.'
    conn.commit()
    return result

def get_authors_by_competency_id(conn,
                                 competency_id: int) -> list[
                                    int, str, str, float, str]:
    """Returns all authors with a given competency with its
    relevancy and status.

    Args:
        conn (Connection): Connection to the database
        competency_id (int): Id of the competency

    Returns:
        list: List[author_id, first_name, last_name, abstract_id, relevancy, status]
    """
    sql_get_authors = """SELECT auth.author_id, auth.first_name,
                         auth.last_name, df.abstract_id, df.relevancy, status
                         FROM author auth JOIN has_competency hc
                         ON auth.author_id = hc.author_id
                         LEFT JOIN derived_from df
                         ON df.competency_id = hc.competency_id
                         JOIN written_by wb ON wb.author_id = auth.author_id
                         AND wb.abstract_id = df.abstract_id
                         WHERE hc.competency_id= ?;"""
    cursor = conn.cursor()
    cursor.execute(sql_get_authors, (competency_id,))
    result = cursor.fetchall()
    if result is None:
        return 'There are no people with this competency.'
    conn.commit()
    return result

def get_abstracts_by_author(conn, author_first_name: str,
                            author_last_name: str) -> list[
                                int, int, str, str, str]:
    """Returns all abstracts of a given author.

    Args:
        conn (Connectino): Connection to the database
        author_first_name (str): First name of the author
        author_last_name (str): Last name of the author

    Returns:
        list: list[abstract_id, year, title, content, institution]
    """
    sql_get_abstracts = """SELECT abs.abstract_id, abs.year, abs.title,
                           abs.content, abs.institution
                           FROM abstract abs JOIN
                           written_by wb ON abs.abstract_id
                           = wb.abstract_id JOIN author auth
                           ON wb.author_id = auth.author_id
                           WHERE auth.first_name = ? AND
                           auth.last_name = ?;"""

    cursor = conn.cursor()
    cursor.execute(sql_get_abstracts, (author_first_name, author_last_name))
    result = cursor.fetchall()
    if result is None:
        return 'There are no abstracts from this author.'
    conn.commit()
    return result

def get_abstracts_with_competency(conn, competency_id: int,
                                  author_id: int) -> list[int]:
    """Returns all abstracts_ids of the abstracts that proof that an author has
    a given competency.

    Args:
        conn (Connection): Connection to the database
        competency_id (int): Id of the competency
        author_id (int): Id of the author

    Returns:
        list: list[abstract_id]
    """
    sql_get_abstracts_with_competency = """SELECT wb.abstract_id
                                           FROM derived_from df
                                           JOIN written_by wb
                                           ON df.abstract_id = wb.abstract_id
                                           WHERE df.competency_id = ?
                                           AND wb.author_id = ?
                                           """
    cursor = conn.cursor()
    cursor.execute(sql_get_abstracts_with_competency,
                   (competency_id, author_id))
    abstracts = cursor.fetchall()
    conn.commit()
    return abstracts

def get_ranking_score(conn, author_id, competency_id) -> int:
    """Returns the ranking score of a given competency for a given author.

    Args:
        conn (Connection): Connection to the database
        author_id (int): Id of the author
        competency_id (int): Id of the competency

    Returns:
        _type_: _description_
    """
    FAILURE_DEFAULT = -1
    sql_get_relevancies = """SELECT relevancy
                             FROM derived_from df JOIN
                             written_by wb ON df.abstract_id = wb.abstract_id
                             WHERE competency_id = ? AND
                             author_id = ?
                            """
    cursor = conn.cursor()
    # getting all relevancies of the author and competency from the ML model
    cursor.execute(sql_get_relevancies, (competency_id, author_id))
    relevancies = cursor.fetchall()
    if relevancies is None or -1 in relevancies:    # no relevancies or dummy relevancies
        return FAILURE_DEFAULT
    conn.commit()

    # getting the author name from the database
    author_first_name, author_last_name = get_author_name(conn, author_id)
    if author_first_name is None and author_last_name is None:
        return FAILURE_DEFAULT

    # getting all abstracts by the author
    abstracts_by_author = get_abstracts_by_author(conn, author_first_name,
                                                  author_last_name)
    if abstracts_by_author == 'There are no abstracts from this author.':
        return FAILURE_DEFAULT
    total_abstracts = len(abstracts_by_author)  # amount of abstracts

    # getting the abstracts of the author that show the competency
    abstracts_with_competency = get_abstracts_with_competency(conn,
                                                              competency_id,
                                                              author_id)
    if abstracts_with_competency == []:
        return FAILURE_DEFAULT
    amount_abstracts_with_competency = len(abstracts_with_competency)

    proportion_competency = amount_abstracts_with_competency / total_abstracts
    mean_relevancy = np.mean(relevancies)

    # no bonus if 1/1 abstract shows competency
    if amount_abstracts_with_competency != 1 and total_abstracts != 1:
        bonus = proportion_competency * (1 - mean_relevancy)
    else:
        bonus = 0

    # calculation of relevancy: relevancy mean plus bonus for proportion with the competency
    ranking_score = mean_relevancy + bonus
    ranking_score = round(ranking_score*100) / 100

    return ranking_score

def get_author_name(conn, author_id: int) -> list[str, str]:
    """Returns the name of an author.

    Args:
        conn (Connection): Connection to the database
        author_id (int): Id of the author

    Returns:
        list: [first_name, last_name]
    """
    sql_get_author_name = """SELECT first_name, last_name
                             FROM author
                             WHERE author_id = ?
                            """
    cursor = conn.cursor()
    cursor.execute(sql_get_author_name, [author_id])

    author = cursor.fetchone()
    if author is None:
        return None, None
    conn.commit()
    return author

def get_all_authors(conn) -> list[int, str, str]:
    """Returns all entries in the author relation in the database.

    Args:
        conn (Connection): Connection to the database

    Returns:
        list: list[author_id, first_name, last_name]
    """
    sql_get_authors = """SELECT * FROM author;"""
    cursor = conn.cursor()
    cursor.execute(sql_get_authors)
    result = cursor.fetchall()
    if result is None:
        return ("Something went wrong. Result for the query to fetch",
                "all entries of the author relation is None.")
    conn.commit()
    return result

def change_status(conn, author_id: int, competency_id: int,
                  competency_status: str) -> list[str]:
    """Changes given competency status in database of author with competency

    Args:
        conn (Connection): Connection to the database
        author_id: author where it should be changed
        competency_id: for which competency the status should be changed
    """
    sql_change_status = """ UPDATE has_competency
                            SET status = ?
                            WHERE author_id = ? AND
                            competency_id = ?
                        """
    cursor = conn.cursor()
    cursor.execute(sql_change_status,
                   (competency_status, author_id, competency_id))
    cursor.fetchall()
    conn.commit()
    result = ["success"]
    return result

def get_author_id_by_full_name(conn, full_name: str) -> int:
    """Returns the id of an author by its name or creates an id if the author's
    id has not been created yet.

    Args:
        conn (Connection): Connection to the database
        full_name (str): Full name of the author

    Returns:
        int: Id of the author
    """
    sql_get_author_id_by_full_name = """SELECT author_id
                                        FROM author
                                        WHERE first_name || ' ' || last_name =
                                        '{}'""".format(full_name)
    cursor = conn.cursor()
    cursor.execute(sql_get_author_id_by_full_name)
    result = cursor.fetchone()
    conn.commit()
    return result


import sys
from collections import defaultdict
sys.setrecursionlimit(10**6)
input = sys.stdin.readline

n, m = map(int, input().split())
cnt = 0
move = [(1, 0), (-1, 0), (0, 1), (0, -1)]
visited = [[0] * m for _ in range(n)]
maps = []
for _ in range(n):
    tmp = list(map(int, input().split()))
    cnt += tmp.count(1)
    maps.append(tmp)

def check(x, y, t):
    for dx, dy in move:
        nx = x + dx
        ny = y + dy

        if 0 <= nx < n and 0 <= ny < m:
            if visited[nx][ny] != t:
                if maps[nx][ny] == 1:
                    c[nx, ny] += 1
                    if c[nx, ny] == 2:
                        arr.add((nx, ny))
                else:
                    visited[nx][ny] = t
                    check(nx, ny, t)

ans = t = 0
while cnt:
    arr = set()
    c = defaultdict(int)
    t += 1
    visited[0][0] = t
    check(0, 0, t)
    cnt -= len(arr)
    for x, y in arr:
        maps[x][y] = 0

    ans += 1

print(ans)


from django.contrib import admin
from .models import Item,Slot,Cart,Order,Contact,Phone
from django.contrib import messages
# Register your models here.
class ItemAdmin(admin.ModelAdmin):
    list_display=('item_name','category','subcategory','available','price')

    def make_available(modeladmin,request,queryset):
        queryset.update(available=True)
    def make_unavailable(modeladmin,request,queryset):
        queryset.update(available=False)

    admin.site.add_action(make_available, "Make available")
    admin.site.add_action(make_unavailable, "Make Unavailable")

admin.site.register(Item,ItemAdmin)
admin.site.register(Slot)
admin.site.register(Cart)

class OrderAdmin(admin.ModelAdmin):
    list_display = ('order_id', 'amount', 'OrderBy','slottime','placed','delivery','paid','status','cancel')
    #actions = ['make_Confirmed']
    def make_Confirmed(modeladmin, request, queryset):
        queryset.update(status = 'Confirmed')
        messages.success(request, "Selected Record(s) Marked as Confirmed Successfully !!")

    def make_Not_Confirmed(modeladmin, request, queryset):
        queryset.update(status = 'Not_Confirmed')
        messages.success(request, "Selected Record(s) Marked as Not_Confirmed Successfully !!")

    def make_paid(modeladmin,request,queryset):
        queryset.update(paid=True)
    def make_unpaid(modeladmin,request,queryset):
        queryset.update(paid=False)

    admin.site.add_action(make_Confirmed, "Make Confirmed")
    admin.site.add_action(make_Not_Confirmed, "Make Not_Confirmed")
    admin.site.add_action(make_paid, "Make Paid")
    admin.site.add_action(make_unpaid, "Make Unpaid")
#show_average.short_description = "Average"

admin.site.register(Order,OrderAdmin)
#admin.site.register(Tprice)
class ContactAdmin(admin.ModelAdmin):
    list_display=('msg_id','name','email','phone','order_id','desc')
admin.site.register(Contact,ContactAdmin)

class PhoneAdmin(admin.ModelAdmin):
    list_display=['phone','author']

admin.site.register(Phone,PhoneAdmin)


import cgi
import os
from google.appengine.ext.webapp import template
from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db

import sys
sys.path = ['..'] + sys.path

from datamodel import *
from utils import *

class SiteView(webapp.RequestHandler):
	def get(self, siteURL):

		theSite = getSiteFromUrl(siteURL)
		if not theSite:
			self.redirect('/')

		if not theSite.backgroundColor:
			theSite.backgroundColor = "#ccc"
			theSite.put()

		if not theSite.views:
			theSite.views = 0

		theSite.views = theSite.views + 1
		theSite.put()

		siteID = theSite.key().id()

		items_query = Item.all().order('-date')
		items_query.filter('siteID =', int(siteID))
		items = items_query.fetch(100)

		userInfo, loggedIn, login_url = getUserStatus(self)
		admin = isAdmin(theSite)

		#instead of returning ideas and votes, return a list of
		#tuples of ideas and votes, this way we can know if the user has voted

		exception = ''

		template_values = {
			'items': items,
			'site': theSite,
			'theUrl': self.request.uri,
			'siteID': siteID,
			'siteName': theSite.name,
			'login_url': login_url,
			'admin': admin,
			'exception': exception,
			'loggedIn' : loggedIn,
			'userInfo': userInfo,
		}

		path = os.path.join(os.path.dirname(__file__), '../views/site.html')
		self.response.out.write(template.render(path, template_values))


import collections

class Solution(object):

    def dfs(self, v, level):

        self.visited.add(v)

        if level % 2 == 0:
           self.on_the_path_even.add(v)
        else:
           self.on_the_path_odd.add(v)

        for w in self.adjList[v]:
            if w not in self.visited:
                if not self.dfs(w, level+1):
                    return False
            elif level % 2 == 0 and w in self.on_the_path_even:
                #print(f"Cycle detected: found a back edge from {v} to {w}.")
                return False
            elif level % 2 == 1 and w in self.on_the_path_odd:
                return False

        if level % 2 == 0:
           self.on_the_path_even.remove(v)
        else:
           self.on_the_path_odd.remove(v)

        return True

    def possisbleBipartition(self, N, dislikes):
        """
        :type N: int
        :type dislikes: List[List[int]]
        :rtype: bool
        """

        self.adjList = collections.defaultdict(list)

        for e in dislikes:
            w, v = e[0], e[1]
            self.adjList[w].append(v)
            self.adjList[v].append(w)

        self.visited = set()
        self.on_the_path_odd = set()
        self.on_the_path_even = set()

        for i in range(1, N+1):
            if not self.dfs(i, 0):
                return False
        return True

if __name__ == "__main__":
    print(Solution().possisbleBipartition(4, [[1,2],[1,3],[2,4]]))
    print(Solution().possisbleBipartition(3, [[1,2],[1,3],[2,3]]))
    print(Solution().possisbleBipartition(5, [[1,2],[2,3],[3,4],[4,5],[1,5]]))


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import migrations, models

class Migration(migrations.Migration):

    dependencies = [
        ('backend', '0017_auto_20161227_0023'),
    ]

    operations = [
        migrations.AddField(
            model_name='fit',
            name='picture_en',
            field=models.ImageField(upload_to=b'fit', null=True, verbose_name='\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435'),
        ),
        migrations.AddField(
            model_name='fit',
            name='picture_ru',
            field=models.ImageField(upload_to=b'fit', null=True, verbose_name='\u0418\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0435'),
        ),
    ]


"""
Adapted from https://github.com/guillaume-be/rust-bert/blob/master/utils/convert_model.py
"""

from pathlib import Path
import numpy as np
import torch
import subprocess
import argparse
import os

if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        "Utility script to convert a pytorch transformer model to a format that can be loaded in libtorch/tch")
    parser.add_argument("--model_path", help="Path to pytorch model")
    parser.add_argument(
        "--output_path", help="Folder path to output the converted weights")
    args = parser.parse_args()

    model_path, output_path = args.model_path, args.output_path

    assert os.path.exists(model_path), "Model path is not a valid path!"
    os.makedirs(output_path, exist_ok=True)

    weights = torch.load(model_path, map_location='cpu')['model'].state_dict()

    np_weights = {}
    for k, v in weights.items():
        k = k.replace("gamma", "weight").replace("beta", "bias")
        np_weights[k] = np.ascontiguousarray(v.numpy())

    npz_path = os.path.join(output_path, 'model.npz')
    np.savez(npz_path, **np_weights)
    new_basename = os.path.basename(model_path).rsplit('.', 1)[0] + ".ot"

    rust_model_path = os.path.join(output_path, new_basename)
    toml_location = (Path(__file__).resolve() / '..' /
                     '..' / 'Cargo.toml').resolve()
    subprocess.run(
        ['cargo', 'run', '--bin=convert_tensors', '--manifest-path=%s' %
            toml_location, '--', "-p", npz_path, "-r", rust_model_path],
    )


from django import forms
from .models import Post, Comment

class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ('title', 'content',)

    title = forms.CharField(
        label='제목',
        label_suffix='',
        widget=forms.TextInput(
            attrs={'class': 'form-control form-field', 'placeholder': '제목',}
        )
    )

    content = forms.CharField(
        label='내용',
        label_suffix='',
        widget=forms.Textarea(
            attrs={'class': 'form-control form-field', 'placeholder': '내용',}
        )
    )

class CommentForm(forms.ModelForm):
    class Meta:
        model = Comment
        fields = ('content',)


#!/usr/bin/env python3
# python base_quantitatif.py
# Auteur: Matthew Wright, CPA, PSM, ACA - pythonfin@proton.me
# Version: 1.0

# importations standard
from typing import Tuple, Any
from datetime import datetime

# importations de tiers
import pandas as pd
import yfinance as yf
import numpy as np
import matplotlib.pyplot as plt

# importations d'applications locales

class QuantitatifCalculs:
    """
    Classe de base

    Paramètres
    ----------
    self.yf_data : tuple
        Tuple[pd.DataFrame] contenant les données yf.download stock ticker de l'indice de temps
    self.tickers : list
        les symboles boursiers à utiliser dans les calculs
    """

    def __init__(self, tickers):
        self.yf_data = tuple()
        self.tickers = tickers

    def charger_donnees(self, index: str, **kwargs: Any):
        """
        Récupère les données historiques pour les tickers et ^GSPC en un seul appel.
        yf.download s'appuie sur une chaîne de tickers séparés par un espace, par exemple 'SCGLY PFE'.

        Args:
            :param index: indice comparatif à utiliser pour le calcul du bêta
            :type index: "str"

            :param kwargs: Arguments facultatifs à passer à la fonction yf.download.

            :Arguments de mots-clés:
                start (str): La date de début au format YYYY-MM-DD
                end (str): La date de fin au format YYYY-MM-DD
                group_by (str): spécifie comment regrouper les données téléchargées
                    (par exemple "ticker" pour le regroupement par symbole de téléscripteur,
                    "column" pour le regroupement par colonne de données)
                interval = '1d' : La période d'intervalle de temps à utiliser dans les calculs bêta.
                    Intervalles valides: [1m, 2m, 5m, 15m, 30m, 60m, 90m, 1h, 1d, 5d, 1wk, 1mo, 3mo]
                auto_adjust (bool): ajuster automatiquement les calculs (la valeur par défaut est True)
                prepost (bool): inclure les données de négociation avant et après le marché (par défaut, False)
                threads (int): spécifiant le nombre de threads à utiliser pour le téléchargement (1 par défaut)

        Retours:
            None: Ceci charge juste les données df dans self.yf_data

        Raises:
            ValueError: Si ticker n'est pas trouvé, ou s'il y a une erreur dans la récupération des données.

        Exemple :
            >>> self.charger_donnees("^GSPC", start='2020-01-01', end='2020-12-31', interval='1d')
        """
        try:
            stock_str = " ".join(self.tickers)

            data: Tuple[pd.DataFrame] = yf.download(stock_str + " " + index, **kwargs, group_by='ticker')

            # Vérifier si les données ne sont pas vides
            if data.empty:
                raise ValueError("yf.download ne s'est pas terminé correctement pour la liste de téléscripteurs")

            # Vérifier si les données d'index sont disponibles
            if index not in data:
                raise KeyError(f"Données pour le {index} n'était pas chargé")

            self.yf_data = data

        except (KeyError, ValueError) as e:
            print("Error:", e)
            return None

        except Exception as e:
            print("Unknown error:", e)
            return None

class QuantitatifBeta(QuantitatifCalculs):
    """ Commencez par les questions de l'analyse quantitative de base"""
    def __init__(self, tickers):
        super().__init__(tickers)
        self.betas = []

    def preparer_beta_calculs(self, index: str, date_range: pd.DatetimeIndex, commencer: str):
        """
        effectuer toutes les préparations du calcul du bêta

        Args:
            :param index: indice comparatif à utiliser pour le calcul du bêta
            :type index: "str"

            :param commencer: date de début pour ce segment des calculs bêta
            :type commencer: "str"

            :param date_range: Pandas df de l'intégralité de l'index date-heure sur lequel il faut itérer
            :type date_range: "pd.DatetimeIndex"

        Retourne:
            dict: Les valeurs bêta des tickers, avec deux décimales.

        Raises:
            ValueError: Si le téléscripteur n'est pas trouvé,
                        ou s'il y a une erreur dans la récupération des données.
            KeyError: Si le téléscripteur n'a pas été chargé dans le fichier yf.download
        """
        try:
            df_betas = []

            # Vérifiez que la plage de dates n'est pas vide.
            if date_range.empty:
                raise ValueError("pas de plage de dates - vide DateTimeIndex")

            for end_date in date_range:
                betas = self._calculs_beta(index=index, commencer=commencer, fin=end_date)

                df = pd.DataFrame(betas, index=[end_date])
                df_betas.append(df)

                print(f'\nla date du jour est {end_date}')
                for ticker, beta_val in betas.items():
                    print(f'Ticker: {ticker} - avec le bêta de {beta_val}')

            self.betas = pd.concat(df_betas)

        except ValueError as e:
            print(f"Erreur: {e}")

        except Exception as e:
            print("Erreur inconnue:", e)
            return None

    def _calculs_beta(self, index: str, commencer: str, fin: str) -> dict[str, float] | None:
        """
        Bêta : mesure de la volatilité d'une action par rapport à l'ensemble du marché
        (métrique typique SP500)
        Calculez le bêta pour un symbole boursier donné.

        Args:
            :param index: indice comparatif à utiliser pour le calcul du bêta
            :type index: "str"

            :param commencer: date de début pour ce segment des calculs bêta
            :type commencer: "str"

            :param fin: date de fin pour ce segment des calculs bêta
            :type fin: "str"

        Retourne:
            dict: les valeurs bêta des tickers, en deux décimales

        Raises:
            ValueError: Si le téléscripteur n'est pas trouvé,
                        ou s'il y a une erreur dans la récupération des données.
            KeyError: Si le téléscripteur n'a pas été chargé dans le fichier yf.download
        """

        try:
            betas_dict = {}

            # boolean mask filtre par jour
            mask = (self.yf_data.index >= commencer) & (self.yf_data.index <= fin)
            df_yf_data = self.yf_data.loc[mask]

            # Effectuer des contrôles d'erreurs
            if df_yf_data.empty:
                err_str = "yf.download ne s'est pas terminé correctement pour la liste de téléscripteurs"
                raise ValueError(err_str)

            if index not in df_yf_data:
                raise KeyError(f"Données pour le {index} n'était pas chargé")

            # Calculer les rendements des indices en utilisant des opérations vectorielles
            sp500_returns = df_yf_data[index]['Adj Close'] \
                .values[1:] / df_yf_data[index]['Adj Close'].values[:-1] - 1

            for ticker in self.tickers:
                if ticker not in df_yf_data:
                    raise KeyError(f"data for {ticker} wasn't loaded")

                # Calculer les rendements quotidiens en utilisant des opérations vectorielles
                stock_returns = df_yf_data[ticker]['Adj Close'] \
                    .values[1:] / df_yf_data[ticker]['Adj Close'].values[:-1] - 1

                # Vérifiez que les données de retour sont suffisantes pour effectuer les calculs de bêta.
                if len(stock_returns) < 2 or len(sp500_returns) < 2:
                    raise ValueError(
                        f"peut pas calculer le bêta pour {ticker} - manque de données suffisantes")

                # Calculez le bêta de l'action
                beta = np.cov(stock_returns, sp500_returns)[0, 1] / np.var(sp500_returns)

                betas_dict[ticker] = round(beta, 2)

            return betas_dict

        except (KeyError, ValueError) as e:
            print("Error:", e)
            return None

        except Exception as e:
            print("Unknown error:", e)
            return None

    def plot_betas(self):
        """
        En utilisant les valeurs de bêta actuelles, crée un graphique de résultats
        des bêta en utilisant matplotlib et trace les valeurs de self.tickers.
        """

        try:
            if not isinstance(self.betas, pd.DataFrame):
                print("Erreur : calculate_beta.betas n'est pas un DataFrame")
                return None

            plt.plot(self.betas.index, self.betas)

            plt.title('Bêta des actions au fil du temps')
            plt.xlabel('Date')
            plt.ylabel('Bêta')

            plt.legend(self.tickers, loc='lower left')

            # Créez un timbre horodateur au format "YYYY-MM-DD_HHM-MM-SS"
            # et sauvegardez-le .png des résultats de bêta.
            now = datetime.now()
            datetime_stamp = now.strftime("%Y-%m-%d_%H-%M-%S")
            save_str = 'resultat/beta_' + datetime_stamp + '.png'

            plt.savefig(save_str)

        except Exception as e:
            print(f'Error: {e}')
            return None


import time

import openai

import streamlit as st

st.title("✍ AI_카피라이터")
st.subheader("AI를 이용하여 손쉽게 마케팅 문구를 생성해보세요.")
openai.api_key = st.secrets["OPENAI_API_KEY"]

auto_complete = st.toggle(label="예시로 채우기")
with st.form("form"):
    col1, col2, col3 = st.columns(3)
    with col1:
        example_brand = "카누"
        name = st.text_input(
            label="제품/브랜드 이름(필수)",
            value=example_brand if auto_complete else "",
            placeholder=example_brand
        )
    with col2:
        max_length = st.number_input("최대 단어 수", min_value=5, max_value=20, step=1, value=10)
    with col3:
        num = st.number_input("생성할 문구 수", min_value=1, max_value=10, step=1, value=5)
    example_desc = "집에서도 카페 느낌의 아메리카노 맛이 나는 커피 믹스"
    desc = st.text_input(
        label="제품 간단 정보(필수)",
        value=example_desc if auto_complete else "",
        placeholder=example_desc
    )

    st.text("포함할 키워드(최대 3개까지 허용)")
    col1, col2, col3 = st.columns(3)
    with col1:
        example_keyword_one = "브라질"
        keyword_one = st.text_input(
            label="keyword_1",
            label_visibility="collapsed",
            placeholder=example_keyword_one,
            value=example_keyword_one if auto_complete else ""
        )
    with col2:
        example_keyword_two = "카페"
        keyword_two = st.text_input(
            label="keyword_2",
            label_visibility="collapsed",
            placeholder=example_keyword_two,
            value=example_keyword_two if auto_complete else ""
        )
    with col3:
        example_keyword_three = "공유"
        keyword_three = st.text_input(
            label="keyword_3",
            label_visibility="collapsed",
            placeholder=example_keyword_three,
            value=example_keyword_three if auto_complete else ""
        )
    submitted = st.form_submit_button("제출하기")
if submitted:
    if not name:
        st.error("브랜드 혹은 제품의 이름을 입력해주세요")
    elif not desc:
        st.error("제품의 간단한 정보를 입력해주세요")
    else:
        with st.spinner('AI 카피라이터가 광고 문구를 생성 중입니다...'):
            time.sleep(3)
        st.success("광고 문구를 생성했습니다.")


from django.shortcuts import render, redirect, get_list_or_404
from django.views import generic
from django.conf import settings
from newsapi import NewsApiClient
import requests
import json
from.models import Topics

class IndexView(generic.TemplateView):
    template_name = "news/index.html"

    def get_context_data(self, **kwargs):
        context = super(IndexView, self).get_context_data(**kwargs)
        context['topic'] = get_list_or_404(Topics, domain_tags=self.kwargs.get("country_name"))
        context['domain'] = self.kwargs.get("country_name")
        context['news_type'] = 'all'
        return context

class TopIndexView(generic.TemplateView):
    template_name = "news/index.html"

    def get_context_data(self, **kwargs):
        context = super(TopIndexView, self).get_context_data(**kwargs)
        context['topic'] = get_list_or_404(Topics, domain_tags=self.kwargs.get("country_name"), top_news="top")
        context['domain'] = self.kwargs.get("country_name")
        context['news_type'] = 'top'
        return context

class ForeignView(generic.TemplateView):
    template_name = "news/foreign.html"
    def get_context_data(self, **kwargs):
        context = super(ForeignView, self).get_context_data(**kwargs)
        api_world = " https://coronavirus-19-api.herokuapp.com/all"
        api = "https://coronavirus-19-api.herokuapp.com/countries"
        api_japan = "https://coronavirus-19-api.herokuapp.com/countries/japan"
        r_world = requests.get(api_world)
        r = requests.get(api)
        r_japan = requests.get(api_japan)
        data_world = json.loads(r_world.text)
        data = json.loads(r.text)
        data_jp = json.loads(r_japan.text)
        context['corona'] = sorted(data, key=lambda x:x['cases'], reverse=True)
        context['world_corona'] = data_world
        context['jp_corona'] = data_jp

        return context

# Create your views here.


#! /usr/bin/env python

from __future__      import division
from numpy           import pi, sin, cos, sqrt, array, linspace, zeros
from scipy.integrate import odeint
from scipy.signal    import lti, lsim
from matplotlib      import pyplot as plt

R   = 15            # Resistance (ohms)
L   = 16e-3         # Inductance (henrys)
C   = 333e-6        # Capacitance (farads)
Q   = 0.66          # Initial charge stored in capacitor at t = 0
f   = 60            # Input voltage frequency
omg = 2*pi*f
phi = 25*(pi/180)   # Phase of input voltage in radians
V0  = sqrt(2)*110   # Input voltage amplitude

# Defining the system in terms of its coefficients in Laplace space
num = [C, 0]
den = [L*C, R*C, 1]
sys = lti(num, den)

t = linspace(0, .1, 100)
u = V0 * sin(omg*t + phi)

# Calculating the current
T, i, _ = lsim(sys, u, t)

# Plots
plt.plot(T, i)
plt.xlim([0, .1])
plt.xlabel('Time $t$ (s)')
plt.ylabel('Current $I(t)$ (A)')
plt.grid()
plt.legend(['$I(t)$'])
plt.show()


from flask import Flask
from flask_ask import Ask, statement, question

app = Flask(__name__)
ask = Ask(app, '/')

@ask.launch
def start():
    return question('''Je suis Alexa et je suis ici pour t'aider a creer ton planing jour a jours . Dis moi ton nom ?''')

@ask.intent('HelloIntent')
def bonjour(nom):
    if nom is None:
        return statement("Je ne connais pas ce nom ,desole")
    else:
        return question("Bonjour {} tu veux creer ton planing pour aujourd'hui ?".format(nom))

@ask.intent('AcesoIntent')
def aceso(reponse):
    if reponse == 'oui' or reponse == 'Oui':
        return question ('Ok, alors dis moi le premier événement de la journée. ?')
    return question ('Ok, alors dis-moi une tache  ?')
task = []

@ask.intent('TareasIntent')
def planing (tareas):
    if tareas is None:
        task.append(tareas)
        return question('a quel heure ?')
    else:
        task.append(tareas)
    return question ('Tu as ajoute : {} a ton planning . cette tache tu vas la faire a quel heure ?'.format(tareas))

@ask.intent('HeureIntent')
def duree(temps):
    if temps is None:
        return question('La tache va se passer a {} : tout pour cette tache ?'''.format(temps))
    else:
        return question('La tache va se passer a {} : tout pour cette tache ?'''.format(temps))

@ask.intent('TerminarIntent')
def fini(terminar):
    if terminar is None :
        return statement('La nouvelle tache est ajoutee avec succes a ton planing. AU REVOIR ')
    else:
        return statement('La nouvelle tache est ajoutee avec succes a ton planing. au revoir. ')

if __name__ == '__main__':
    app.run()


import pandas as pd
import pytest

import src.utils as utils

def test_load_input_file(test_file):
    # Load a correct file
    df = utils.load_input_file(test_file)
    assert type(df) == pd.DataFrame

    # Load a file that does not end in .csv
    with pytest.raises(AssertionError):
        utils.load_input_file("test_file.txt")
    # Load a file that does not exist
    with pytest.raises(OSError):
        utils.load_input_file("this_file_doesnt_exist.csv")

def test_check_input_columns(test_df):
    reference_columns = ["UserId", "Event", "Category"]
    assert utils.check_input_columns(test_df, reference_columns)

    reference_columns = ["UserId", "Event", "Category", "Unknown_column"]
    assert not utils.check_input_columns(test_df, reference_columns)

def test_feature_engineering(test_df, reference_df):
    # Test the feature engineering for training
    df = utils.feature_engineering(test_df, training=True)
    columns_training = ["UserId", "Fake", "count_event", "count_category"]
    assert all(_ in df.columns for _ in columns_training)
    assert reference_df.equals(df)

    # Test the feature engineering for evaluation / inference
    df = utils.feature_engineering(test_df, training=False)
    assert "Fake" not in df.columns
    assert reference_df.drop(columns=["Fake"]).equals(df)


"""
Play random episode from How I met your Mother
Any Season
Any episode
"""

import os
import random
import pickle
import vlc
import time

# Path to all seasons folder
PATH = "E:/Series/How-I-met-your-mother"
pickle_path = "./episodes"
TOTAL_EPISODES = 208
DURATION = 1260

def create_pickle(path):
	"""
		Function takes the absolute path of all HIMYM episodes in
		the format
		It does not matter what/how you name your episodes or seasons
		- path
		    - season 1
		        - episode 1
		        - episode 2
		        .
		        .
		        .
		    - season 2
		    - season 3
		    .
		    .
		It generates a pickle file of episode index (starting from 0)
		and the absolute path of the video file

	"""
	index = 0
	dct = {}

	# scan all sub folders and store episode paths in dict
	seasons = os.listdir(path)
	for season in seasons:
		print(season)
		season_path = os.path.join(path, season)
		episodes = os.listdir(season_path)
		for episode in episodes:
			episode_path = os.path.join(season_path, episode)
			dct[index] = episode_path
			index += 1

	# store dict in current folder
	try:
		pickle.dump(dct, open("episodes", "wb"))
		print("Pickle File created")
	except:
		print("Something went wrong. Checkout Readme.md")

def read_pickle(pickle_path = "./episodes", index=0):
	dct = pickle.load(open(pickle_path, "rb"))
	episode_path = dct[index]
	TOTAL_EPISODES = len(dct)
	print("---")
	return episode_path

def play_video(video_path):
	"""
		Function runs the video in vlc media player
	"""
	try:
		media = vlc.MediaPlayer(video_path)
		media.play()
		time.sleep(DURATION)

	except Exception as e:
		print("Terminated")
		print(e)

def main():
	print("Ba baa baaa baa")
	#print(os.listdir(path))
	total_episodes = 0
	if(os.path.exists(pickle_path)):
		print("file is already there")
		read_pickle()
	else:
		create_pickle(PATH)
	random_episode_index = random.randint(0, TOTAL_EPISODES)
	random_episode_path = read_pickle(pickle_path, random_episode_index)
	print("Playing episode ", random_episode_path)

	play_video(random_episode_path)

if __name__ == "__main__":
	main()


from pyspark import SparkContext
from matplotlib import pyplot as plt

sc = SparkContext()

# UserID::Gender::Age::Occupation::Zip-code
movie_file = sc.textFile('./ml-1m/users.dat')

def sex_num(row):
    sexs = list(row[1])
    sex = set(sexs)
    return [(row[0] + s, sexs.count(s)) for s in sex]

users = movie_file.map(lambda row: row.split("::"))\
    .map(lambda row: (row[3], row[1]))\
    .groupByKey().flatMap(sex_num).collect()

labels = []
sizes = []
for key, value in users:
    if key[:-1] in ("1", "6", "16"):
        labels.append(key)
        sizes.append(value)

plt.figure(figsize=(6, 6))  # 调节图形大小

patches, text1, text2 = plt.pie(sizes,
                                labels=labels,
                                autopct='%0.2f%%',  # 数值保留固定小数位
                                shadow=False,  # 无阴影设置
                                startangle=90,  # 逆时针起始角度设置
                                pctdistance=0.6)  # 数值距圆心半径倍数距离

# patches饼图的返回值，texts1饼图外label的文本，texts2饼图内部的文本
# x，y轴刻度设置一致，保证饼图为圆形
plt.axis('equal')
plt.show()