from random import shuffle

import numpy as np

from kor_char_parser import decompose_str_as_one_hot
from utils import to_categorical

class CustomDataset:

    def __init__(self, normal_data_size, slang_data_size, max_len: int, test_normal=None, test_slang=None):

        if test_normal is None and test_slang is None:
            with open('../master_data/slang.txt', 'rt', encoding='utf-8') as f_slang:
                slang_data = f_slang.read().split("\n")

            with open('../master_data/common.txt', 'rt', encoding='utf-8') as f_common:
                common_data = f_common.read().split("\n")

            with open('../master_data/refined_lyrics.txt', 'rt', encoding='utf-8') as f_lyrics:
                lyric_data = f_lyrics.read().split('\n')

            with open('../master_data/hns_cmt.txt', 'rt', encoding='utf-8') as f_hns:
                custom_normal_data = f_hns.read().split('\n')

            # Merging data
            normal_data = common_data + lyric_data + custom_normal_data
            slang_data = slang_data

            # Shuffling
            shuffle(normal_data)
            shuffle(slang_data)

            normal_data = normal_data[:normal_data_size]
            slang_data = slang_data[:slang_data_size]

        else:  # Test dataset
            with open(test_normal, 'rt', encoding='utf-8') as f_normal:
                normal_data = f_normal.read().split('\n')

            with open(test_slang, 'rt', encoding='utf-8') as f_slang:
                slang_data = f_slang.read().split('\n')

        print("plain", len(normal_data))
        print("slang", len(slang_data))

        # Make labels
        # ===============================
        normal_label = [0]*len(normal_data)
        slang_label = [1]*len(slang_data)

        data = normal_data + slang_data
        labels = normal_label + slang_label

        data_labels = list(zip(data, labels))

        shuffle(data_labels)
        self.data, self.labels = zip(*data_labels)

        self.data = list(self.data)
        self.labels = list(self.labels)

        self.data = preprocess(self.data, max_len)
        self.labels = to_categorical(self.labels, 2)
        # self.labels = tf.one_hot(tf.cast(self.labels, tf.uint8), 2)

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

    def __getitem__(self, idx):
        return self.data[idx], self.labels[idx]

def _batch_loader(iterable, n=1):
    length = len(iterable)
    for n_idx in range(0, length, n):
        yield iterable[n_idx:min(n_idx + n, length)]

def preprocess(data: list, max_len: int):

    # In this task, data is one sentence and datum is a char
    vectorized_data = [decompose_str_as_one_hot(datum) for datum in data]
    zero_padding = np.zeros((len(data), max_len), dtype=np.int32)
    for idx, seq in enumerate(vectorized_data):
        original_len = len(seq)  # original vectorized sentence length
        if original_len >= max_len:
            original_len = max_len
            zero_padding[idx, :original_len] = np.array(seq)[:original_len]
        else:
            zero_padding[idx, :original_len] = np.array(seq)

    return zero_padding

if __name__ == '__main__':
    dataset = CustomDataset(max_len=40)
    print(dataset.data[0])


import logging

from marshmallow import Schema, post_load, fields, EXCLUDE
from fuocore.models import ModelExistence

logger = logging.getLogger(__name__)

class BaseSchema(Schema):
    class Meta:
        unknown = EXCLUDE

Schema = BaseSchema

class NeteaseMvSchema(Schema):
    identifier = fields.Int(required=True, data_key='id')
    name = fields.Str(required=True)
    cover = fields.Str(required=True)
    brs = fields.Dict(required=True)

    @post_load
    def create_model(self, data, **kwargs):
        brs = data['brs']
        fhd = hd = sd = ld = None
        for q, url in brs.items():
            if q == '1080':
                fhd = url
            elif q == '720':
                hd = url
            elif q == '480':
                sd = url
            elif q == '240':
                ld = url
            else:
                logger.warning('There exists another quality:%s mv.', q)
        data['q_url_mapping'] = dict(fhd=fhd, hd=hd, sd=sd, ld=ld)
        return NMvModel(**data)

class NeteaseSongSchema(Schema):
    identifier = fields.Int(required=True, data_key='id')
    mvid = fields.Int(required=True)
    title = fields.Str(required=True, data_key='name')
    duration = fields.Float(required=True)
    url = fields.Str(allow_none=True)
    album = fields.Nested('NeteaseAlbumSchema')
    artists = fields.List(fields.Nested('NeteaseArtistSchema'))

    @post_load
    def create_model(self, data, **kwargs):
        album = data['album']
        artists = data['artists']

        # 在所有的接口中，song.album.songs 要么是一个空列表，
        # 要么是 null，这里统一置为 None。
        album.songs = None

        # 在有的接口中（比如歌单列表接口），album cover 的值是不对的，
        # 它会指向的是一个网易云默认的灰色图片，我们将其设置为 None，
        # artist cover 也有类似的问题。
        album.cover = None

        if artists:
            for artist in artists:
                artist.cover = None

        return NSongModel(**data)

class NSongSchemaV3(Schema):
    identifier = fields.Int(required=True, data_key='id')
    mvid = fields.Int(required=True, data_key='mv')
    title = fields.Str(required=True, data_key='name')
    duration = fields.Float(required=True, data_key='dt')
    url = fields.Str(allow_none=True)
    album = fields.Nested('NAlbumSchemaV3', data_key='al')
    artists = fields.List(fields.Nested('NArtistSchemaV3'), data_key='ar')

    @post_load
    def create_model(self, data, **kwargs):
        return NSongModel(**data)

class NeteaseAlbumSchema(Schema):
    identifier = fields.Int(required=True, data_key='id')
    name = fields.Str(required=True)
    cover = fields.Str(data_key='picUrl', allow_none=True)
    # 收藏和搜索接口返回的 album 数据中的 songs 为 None
    songs = fields.List(fields.Nested('NeteaseSongSchema'), allow_none=True)
    artists = fields.List(fields.Nested('NeteaseArtistSchema'))

    @post_load
    def create_model(self, data, **kwargs):
        return NAlbumModel(**data)

class NAlbumSchemaV3(Schema):
    # 如果 album 无效，id 则为 0
    # 只有当 album 无效时，name 才可能为 None
    identifier = fields.Int(required=True, data_key='id')
    name = fields.Str(required=True, allow_none=True)

    @post_load
    def create_model(self, data, **kwargs):
        album = NAlbumModel(**data)
        if album.identifier == 0:
            album.exists = ModelExistence.no
            album.name = ''
        return album

class NeteaseArtistSchema(Schema):
    identifier = fields.Int(required=True, data_key='id')
    name = fields.Str()
    cover = fields.Str(data_key='picUrl', allow_none=True)
    songs = fields.List(fields.Nested('NeteaseSongSchema'))

    @post_load
    def create_model(self, data, **kwargs):
        return NArtistModel(**data)

class NArtistSchemaV3(Schema):
    # 如果 artist 无效，id 则为 0
    # 只有当 artist 无效时，name 才可能为 None
    identifier = fields.Int(required=True, data_key='id')
    name = fields.Str(required=True, allow_none=True)

    @post_load
    def create_model(self, data, **kwargs):
        artist = NArtistModel(**data)
        if artist.identifier == 0:
            artist.exists = ModelExistence.no
            artist.name = ''
        return artist

class NeteasePlaylistSchema(Schema):
    identifier = fields.Int(required=True, data_key='id')
    uid = fields.Int(required=True, data_key='userId')
    name = fields.Str(required=True)
    desc = fields.Str(required=True, allow_none=True, data_key='description')
    cover = fields.Url(required=True, data_key='coverImgUrl')
    # songs field maybe null, though it can't be null in model
    songs = fields.List(fields.Nested(NeteaseSongSchema),
                        data_key='tracks',
                        allow_none=True)

    @post_load
    def create_model(self, data, **kwargs):
        if data.get('desc') is None:
            data['desc'] = ''
        return NPlaylistModel(**data)

class NeteaseUserSchema(Schema):
    identifier = fields.Int(required=True, data_key='id')
    name = fields.Str(required=True)
    playlists = fields.List(fields.Nested(NeteasePlaylistSchema))
    fav_playlists = fields.List(fields.Nested(NeteasePlaylistSchema))
    cookies = fields.Dict()

    @post_load
    def create_model(self, data, **kwargs):
        return NUserModel(**data)

class NeteaseSearchSchema(Schema):
    """搜索结果 Schema"""
    songs = fields.List(fields.Nested(NeteaseSongSchema))
    albums = fields.List(fields.Nested(NeteaseAlbumSchema))
    artists = fields.List(fields.Nested(NeteaseArtistSchema))
    playlists = fields.List(fields.Nested(NeteasePlaylistSchema))

    @post_load
    def create_model(self, data, **kwargs):
        return NSearchModel(**data)

from .models import (  # noqa
    NAlbumModel,
    NArtistModel,
    NPlaylistModel,
    NSongModel,
    NUserModel,
    NMvModel,
    NSearchModel
)  # noqa


__author__ = 'ben'

lines = [line.rstrip('\n') for line in open('input')][1:]

outFile = open("output", "w")

c = 1
for line in lines:
    w = list(line)
    mid = w[0]
    front = []
    back = []
    del w[0]
    for i in w:
        if len(front):
            if ord(i) >= ord(front[0]):
                front.insert(0, i)
            else:
                back.append(i)
        else:
            if ord(i) >= ord(mid):
                front.insert(0, i)
            else:
                back.append(i)
    outFile.write("Case #" + str(c) + ": " + "".join(front) + mid + "".join(back) + "\n")
    c += 1


# 191119 number of community claws with all randomizations, local randomizations, and observed

num_exp = 1000
ana = ana_all_rd
geom_conn = ana.geo_data['centroids'].conn

row_ids = segid_to_skid(ana.geo_data['centroids'].row_ids)
col_ids = segid_to_skid(ana.geo_data['centroids'].col_ids)
gloms = [ana.pn_mapping.skids_to_types(i)[0] for i in col_ids]

conn_data = ana.conn_data['glom_kc_in_claw_unit']
ob_conn, glom_prob, glom_idx_ids = get_conn_prob_idx(conn_data)
sfl_cols = conn_data.col_ids

# check row_ids from geo_data are the same as row_ids from bouton_claw
# and trim it down to claws that receive inputs from unilgomerular PNs
t21 = ana.geo_data['centroids'].row_ids
t22 = ana.conn_data['bouton_claw'].row_ids
t21 == t22
conn_t = ana.conn_data['bouton_claw'].conn['5s']

select = np.where(np.sum(conn_t,1))[0]
row_ids = [row_ids[i] for i in select]
geom_conn = geom_conn[select,:]
conn_t = conn_t[select,:].copy()

ip_gloms = [sfl_cols.index(ana.pn_mapping.skids_to_types(col_ids[np.argmax(conn_t[i,:])])) for i in range(conn_t.shape[0])]

# glom_to_pick is an array; each row represents a claw, ordered as in the KC skeleton id (row_ids above); each row has 5 glom indices that represent 5 boutons closest to the claw
n = 5
including_connected = True

t1 = []

if including_connected:
    for i,v in enumerate(row_ids):
        geom_sort = np.argsort(geom_conn[i,:])
        to_pick = [sfl_cols.index(gloms[j]) for j in geom_sort[:n]]
        t1.append(to_pick)
else:
    for i,v in enumerate(row_ids):
        geom_sort = np.argsort(geom_conn[i,:])
        to_pick = [sfl_cols.index(gloms[j]) for j in geom_sort[:n+1]]
        t2 = ip_gloms[i]
        if t2 in to_pick:
            to_pick = [to_pick[l] for l in range(n+1) if l != to_pick.index(t2)]
        else:
            to_pick = to_pick[:n]
        t1.append(to_pick)

glom_to_pick = np.stack(t1)
rows = np.array(row_ids)
# 200211---------------end (local random bouton set)

comm_ids = [22, 44, 32, 42, 34, 38, 30, 23, 47, 4]
comm_anno_ids = df_lookup('glom_id',comm_ids,'glom_anno_id',glom_btn_table)
ana_obj = ana.conn_data['glom_kc_in_claw_unit']

comm_idx = find_elements(sfl_cols,comm_anno_ids)

local_claw_set = []
stat = []
for t11 in range(num_exp):
    sfl_conn = np.zeros(ob_conn.shape)
    for i,v in enumerate(conn_data.row_ids):
        for j in np.where(rows==v)[0]:
            sfl_conn[i, glom_to_pick[j,np.random.randint(n)]] += 1
    local_claw_set.append(np.sum(sfl_conn[:,comm_idx]))
    print(t11)

# global_claw_set
conn_data = ana.conn_data['glom_kc_in_claw_unit']
ob_conn, glom_prob, glom_idx_ids = get_conn_prob_idx(conn_data)

comm_prob = sum([glom_prob[i] for i in find_elements(glom_idx_ids, comm_ids)])

claw_num = np.sum(ob_conn,1)

global_claw_set = []
sfl_results = []
for i in range(num_exp):
    sfl_conn = get_random_conn(claw_num.shape[0], claw_num, prob=[comm_prob, 1-comm_prob])
    global_claw_set.append(np.sum(sfl_conn,0)[0])

# ob
ob_claw_set = np.sum(ob_conn[:,comm_idx])

# 200326, copy from 200212-Ob_vs_LocalBtnRdModel.py
# Fig3B (200326, PNKC2019_v9_fig_200313DB-ZZfixedSuppl6B.pptx)
fig, ax = plt.subplots()
cols = ['#1f77b4', '#2ca02c']
for i, x in enumerate([global_claw_set, local_claw_set]):
    ax.hist(x, bins=range(1300,2000,15), color = cols[i], edgecolor='black', linewidth=0.8)
ax.plot(ob_claw_set, 4, 'ro', ms=8)

fig.set_size_inches([12,6])
ax.legend(['observed','random bouton model','local random claw model'])
# save_path = '/Users/zhengz11/myscripts/data_results/200226-rerun_comm_claw_hist/'
# fig.savefig(save_path + '200226-comm_claws_hist_LocalvsGlobalvsObserved_dpi600.png', bbox_inches='tight', dpi=600)

# number of community claws in random bouton model vs. observed
# Fig2B (200326, PNKC2019_v9_fig_200313DB-ZZfixedSuppl6B.pptx)
fig, ax = plt.subplots()
ax.hist(global_claw_set, bins=range(1300,2000,15), color = '#1f77b4', edgecolor='black', linewidth=0.8)
ax.plot(ob_claw_set, 4, 'ro', ms=8)
# ax.set_ylim([0,300])

fig.set_size_inches([12,6])
fig.savefig(save_path + '200226-comm_claws_hist_GlobalvsObserved_dpi600.png', bbox_inches='tight', dpi=600)

# below are old comments
#-----------------------------------------------------
# copy from 191028-local_randomization_conditional_input_matrix.py
# 191119 number of community claws with all randomizations, local randomizations, and observed
# 200211---------------begin (local random bouton set)


#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""Module for orbit response matrix calculation.
"""

from __future__ import division
from __future__ import print_function

import time
from functools import reduce

import numpy as np
import numpy.linalg as linalg

def get_orm(lattice, correctors, monitors, **kws):
    """Calculate orbit response matrix (ORM) with defined input.

    Size of *monitors* is ``m``, size of correctors is ``n``, if both x and y
    directions are monitored, size of *monitors* should be doubled. The final
    calculated ORM should be of the shape of ``(m, n)``.

    Every iteration of correctors update, which could be defined by ``scan``
    keyword parameter, series of measured orbit data would be returned from
    :func:`get_orbit`, doing linear polynomial fitting against feeded ``scan``
    values should return one column of ORM data. The column-wise returned
    matrix is the final ORM.

    Parameters
    ----------
    lattice : Lattice
        High-level lattice object.
    correctors : List[CaElement]
        List of correctors from *lattice*.
    monitors : List[CaElement]
        List of monitors, usually BPMs, to measure the beam orbit.

    Keyword Arguments
    -----------------
    source : str
        Orbit data source, ``control`` (default) or ``model``. If ``control``
        is defined, ORM will be measured within *control* environment,
        or ORM will be from *model*, e.g. FLAME model.
    scan : array
        Scan array for correctors, unit: *rad*, default array is
        ``[-0.003, -0.0015, 0, 0.0015, 0.003]``.
    cor_field : str
        Field name for correctors, ``'ANG'`` by default.
    orb_field : tuple[str]
        Field names for monitors to retrieve orbit data, ``('X', 'Y')`` for
        *x* and *y* directions by default.
    wait : float
        Wait time after set value, in *sec*, 1.0 by default.
    xoy : str
        'x'('y') for monitoring 'x'('y') direction,'xy' for both (default).

    Returns
    -------
    ret : array
        ORM with shape ``(m, n)``.

    Todo
    ----
    case of ``source == 'model'``.
    """
    source = kws.get('source', 'control')
    scan = kws.get('scan', np.linspace(-0.003, 0.003, 5))
    cor_field = kws.get('cor_field', 'ANG')
    xoy = kws.get('xoy', 'xy')
    wait = kws.get('wait', 1.0)

    m = len(monitors) * len(xoy)
    n = len(correctors)
    mat_mn = np.zeros([m, n])

    # i <-- 0, m-1
    # B[i] = \Sigma_j=0^{n-1} R[i,j] C[j]
    # ---> iff C[j] != 0 ==> B[i] = R[i,j] C[j]
    # ==> R[i,j] = B[i]/C[j]
    # ==> or: R[i,j] = polyfit(C[i], B[i], 1)[0]
    #
    for i, cor in enumerate(correctors):
        orbit_arr = np.zeros([len(scan), m])
        cor_val0 = getattr(cor, cor_field)
        for iscan, val in enumerate(scan):
            print("Set [{0}] {1}:{2}".format(i+1, cor.name, val))
            setattr(cor, cor_field, val)
            time.sleep(wait)
            orbit_arr[iscan] = get_orbit(monitors, **kws)

        # get mat_mn(k,i)
        for k in range(m):
            mat_mn[k, i] = np.polyfit(scan, orbit_arr[:, k], 1)[0]

        # reset cor and process next col
        setattr(cor, cor_field, cor_val0)
    return mat_mn

def inverse_matrix(m):
    """Get inverse matrix of *m* based on SVD approach, *m* should be general
    rectangle shaped.

    Parameters
    ----------
    m : array
        Matrix.

    Returns
    -------
    ret : array
        Inverse matrix.

    See Also
    --------
    get_orm : Measure orbit response matrix.
    """
    U, s, V = linalg.svd(m)
    min_shape = min(m.shape)
    S_inv = np.zeros(m.shape[::-1], dtype=float)
    S_inv[:min_shape, :min_shape] = np.diag(1.0/s)
    m_inv = reduce(np.dot, (V.T, S_inv, U.T))
    return m_inv

def get_orbit(monitors, **kws):
    """Get beam orbit from defined *monitors*.

    Parameters
    ----------
    monitors : List[CaElement]
        List of monitors, usually BPMs, to measure the beam orbit.

    Keyword Arguments
    -----------------
    orb_field : tuple[str]
        Field names for monitors to retrieve orbit data, ``('X', 'Y')`` for
        *x* and *y* directions by default.
    xoy : str
        'x'('y') for monitoring 'x'('y') direction,'xy' for both (default).

    Returns
    -------
    ret : array
        Monitors readings as beam orbit.
    """
    orb_field = kws.get('orb_field', ('X', 'Y'))
    xoy = kws.get('xoy', 'xy')
    xyfld = zip(range(len(xoy)), orb_field)
    xys = [[getattr(elem, fld) for elem in monitors] for _, fld in xyfld]
    return np.asarray(xys).flatten()

def get_correctors_settings(orm, orbit_diff, inverse=False):
    """Calculate new settings of correctors regarding to BPM readings after
    correction.

    Parameters
    ----------
    orm : array
        Orbit response matrix.
    orbit_diff : array
        Orbit (BPM readings) difference after and before correction.
    inverse : True or False
        If *orm* has already been inversed or not (default).

    Returns
    -------
    ret : array
        Array of corrector settings that should be added to original ones.

    See Also
    --------
    get_orm : Measure orbit response matrix.
    inverse_matrix : Inverse matrix by SVD.
    """
    if not inverse:
        m_inv = inverse_matrix(orm)
    else:
        m_inv = orm

    return np.dot(m_inv, orbit_diff)

def get_index_grid(lattice, correctors, monitors, xoy='xy'):
    """Return the index grid of sub ORM from global ORM for selected
    *correctors* and *monitors* w/ *xoy*.

    The global ORM is measured with all correctors (H + V) and BPMs for
    both x and y direction.

    Parameters
    ----------
    lattice : Lattice
        High-level lattice object.
    correctors : List[CaElement]
        List of correctors from *lattice*.
    monitors : List[CaElement]
        List of monitors, usually BPMs, to measure the beam orbit.
    xoy : str
        'x'('y') for monitoring 'x'('y') direction,'xy' for both (default).

    See Also
    --------
    get_orm : Measure orbit response matrix.
    """
    all_cors = lattice.get_elements(type='HCOR') +  \
               lattice.get_elements(type='VCOR')
    all_bpms = lattice.get_elements(type='BPM')
    # selected correctors columns
    col_idx = [all_cors.index(i) for i in correctors]
    # selected BPM rows, x,x,x....y,y,y...
    bpm_idx = [all_bpms.index(i) for i in monitors]
    if xoy == 'xy':
        bpm_cnt = len(all_bpms)
        row_idx = bpm_idx + [i+bpm_cnt for i in bpm_idx]
    elif xoy == 'x':
        row_idx = bpm_idx
    elif xoy == 'y':
        bpm_cnt = len(all_bpms)
        row_idx = [i+bpm_cnt for i in bpm_idx]
    return np.ix_(row_idx, col_idx)


from typing import List

import attr
import torch
from torch import nn as nn
from torch.nn import functional as F

from data_schema import Span
from scoring import DistanceEmbedder, FFNN
from utils import speaker_label, to_cuda, pairwise_indexes, to_var, pad_and_stack

class PairwiseScorer(nn.Module):

    def __init__(self, span_repr_dim, distance_dim, genre_dim, speaker_dim):
        super().__init__()

        phi_feature_dim = distance_dim + genre_dim + speaker_dim
        ant_scorer_input_dim = span_repr_dim * 3 + phi_feature_dim

        self.distance = DistanceEmbedder(distance_dim)
        self.genre = Genre(genre_dim)
        self.speaker = Speaker(speaker_dim)

        self.score = FFNN(ant_scorer_input_dim)

    def forward(self, spans:List[Span], span_representations, mention_scores):

        mention_ids, antecedent_ids, distances, genres, speakers = zip(*[
            (span.id, ant_span.id, span.end-ant_span.start, span.genre, speaker_label(span, ant_span))
                                                for span in spans
                                                for ant_span in span.antecedent_spans])

        mention_ids = to_cuda(torch.tensor(mention_ids))
        antecedent_ids = to_cuda(torch.tensor(antecedent_ids))

        phi_feature = torch.cat((self.distance(distances),
                         self.genre(genres),
                         self.speaker(speakers)), dim=1)

        def get_representations(ids):
            return torch.index_select(span_representations,0,ids)

        m_r = get_representations(mention_ids)
        a_r = get_representations(antecedent_ids)

        pairs = torch.cat((m_r, a_r, m_r*a_r, phi_feature), dim=1)

        def get_mention_scores(ids):
            return torch.index_select(mention_scores,0,ids)

        m_s = get_mention_scores(mention_ids)#in paper: s_i
        a_s = get_mention_scores(antecedent_ids)#in paper: s_j
        am_s = self.score(pairs)#in paper: s_ij

        coref_scores = torch.sum(torch.cat((m_s, a_s, am_s), dim=1), dim=1, keepdim=True)

        spans = [
            attr.evolve(span,
                        antspan_span=[((ant_span.start, ant_span.end), (span.start, span.end)) for ant_span in span.antecedent_spans]
                        )
            for span, score in zip(spans, coref_scores)
        ]

        list_num_ant_spans = [len(s.antecedent_spans) for s in spans if len(s.antecedent_spans)>0]

        # Split coref scores so each list entry are scores for its antecedents, only.
        # (NOTE that first index is a special case for torch.split, so we handle it here)
        split_scores = [to_cuda(torch.tensor([]))] \
                         + list(torch.split(coref_scores, list_num_ant_spans, dim=0))

        epsilon = to_var(torch.tensor([[0.]]))
        with_epsilon = [torch.cat((score, epsilon), dim=0) for score in split_scores]

        # Batch and softmax
        # get the softmax of the scores for each span in the document given
        probs = [F.softmax(tensr,dim=0) for tensr in with_epsilon]

        # pad the scores for each one with a dummy value, 1000 so that the tensors can
        # be of the same dimension for calculation loss and what not.
        padded_probs = pad_and_stack(probs, value=1000)[0].squeeze()
        return spans, padded_probs

class Genre(nn.Module):
    """ Learned continuous representations for genre. Zeros if genre unknown.
    """

    genres = ['bc', 'bn', 'mz', 'nw', 'pt', 'tc', 'wb']
    _stoi = {genre: idx+1 for idx, genre in enumerate(genres)}

    def __init__(self, genre_dim=20):
        super().__init__()

        self.embeds = nn.Sequential(
            nn.Embedding(len(self.genres)+1, genre_dim, padding_idx=0),
            nn.Dropout(0.20)
        )

    def forward(self, labels):
        """ Embedding table lookup """
        return self.embeds(self.stoi(labels))

    def stoi(self, labels):
        """ Locate embedding id for genre """
        indexes = [self._stoi.get(gen) for gen in labels]
        return to_cuda(torch.tensor([i if i is not None else 0 for i in indexes]))

class Speaker(nn.Module):
    """ Learned continuous representations for binary speaker. Zeros if speaker unknown.
    """

    def __init__(self, speaker_dim=20):
        super().__init__()

        self.embeds = nn.Sequential(
            nn.Embedding(3, speaker_dim, padding_idx=0),
            nn.Dropout(0.20)
        )

    def forward(self, speaker_labels):
        """ Embedding table lookup (see src.utils.speaker_label fnc) """
        return self.embeds(to_cuda(torch.tensor(speaker_labels)))


from django.core.management.base import BaseCommand
from django.conf import settings
import telebot
from PCHelp.models import Staff
from . import settingsbot

class Command(BaseCommand):
    help = 'Телеграмм- бот pyTelegramBotAPI'

    def handle(self, *args, **options):
        bot = telebot.TeleBot(settingsbot.TOKEN)
        print(bot.get_me())

        @bot.message_handler(content_types=["text"])
        def repeat_all_messages(message):  # Название функции не играет никакой роли, в принципе
            bot.send_message(message.chat.id, message.text)

        @bot.callback_query_handler(func=lambda call: True)
        def callback_inline(call):
            # remove inline buttons

            try:
                staffperson = Staff.objects.get(idtelegram=call.from_user.id)
                bot.edit_message_text(chat_id=call.message.chat.id, message_id=call.message.message_id,
                                      text=call.message.text + "\n Ответственный: " + staffperson.firstname + ' ' + staffperson.lastname,
                                      reply_markup=None)
            except:
                bot.answer_callback_query(callback_query_id=call.id, show_alert=False,
                                          text="Не найден сотрудник по telegram id ")

        #if(__name__ ) == 'PCHelp.management.commands.bot2':
        #    bot.polling(none_stop=True)
        bot.polling(none_stop=True)


# first python programme wrote by junius
# +     -     *   /     //    %    **
# and       or      not
import sys

# basic data type
myString = 'Hello World'
myInteger = 1
myBool = True
print (myString, myInteger, myBool)

# int float str bool
myString = "123"
print(int(myString))

#
myInt = 123
print(str(myInt))

# None
nn = None
if not nn:
    print ("I am nn")
else:
    print ("I have value")


#!/usr/bin/env python3
from __future__ import division

'''
Created on Jun 1, 2016

@author: fanxueyi
'''

#extract the exon segments, concatenate them, and write them to a new file

#open the genomic_dna.txt file
dna_file = open("genomic_dna.txt")

#save all character
my_dna = dna_file.read()

#open exons.txt file
exons_file = open('exons.txt')

#create and open a new output file
exons_output = open('multipleExonsOutput.txt', 'a')

#state an list to store the exons
exons=[]

for line in exons_file:
    positionIndex = line.split(",")
    start = int(positionIndex[0])-1
    end = int(positionIndex[1].strip('\n'))-1
    exons.append(my_dna[start,end])

exon_dna = ''

for e in exons:
    exon_dna = exon_dna + e

exons_output.write(exon_dna)

exons_output.close()
exons_file.close()
dna_file.close()


# Name: Qi Haodi
# Section: G3

from lt4_utility import all_users_got_message

# lt4.py
# Warning: do NOT call read_file in select_set. Your code should not read or write to any file system.

def get_pop_followers(followers):
    id_follower_pair = []
    for i in range(len(followers)):
        id_follower_pair.append((i, followers[i]))
    id_follower_pair.sort(key=lambda x: (len(x[1]), x[0]), reverse=True)
    return id_follower_pair

def get_follower_difference(current, coming):
    diff = 0
    result = list(current) + coming[1]
    result.append(coming[0])
    return len(set(result)) - len(current)

def select_set(followers):

    reached = set()
    followers_selected = []
    pop_followers = get_pop_followers(followers)

    while len(reached) != len(followers):
        max_difference = -1
        for follower in pop_followers:
            difference = get_follower_difference(reached, follower)
            if difference > max_difference:
                max_difference = difference
                to_add = follower
        pop_followers.remove(to_add)
        reached = set(list(reached) + to_add[1]+[to_add[0]])
        followers_selected.append(to_add[0])

    return followers_selected


# -*- coding: utf-8 -*-

"""
Class - Background
run() - make the background moving
Created on 2019/12/22
"""

__author__ = "Yihang Wu"

from tkinter import Tk, Canvas

from .utils import get_photo_image

class Background(Canvas):
    _background = []  # list for background id
    _stop = False  # indicate if the background is still rather than moving

    def __init__(self, tk_instance, width, height, fp, animation_speed=50):

        if not isinstance(tk_instance, Tk):
            raise TypeError('Argument "tk_instance" must be an instance of Tk')

        self._width = width
        self._height = height

        self.image_path = fp
        self.animation_speed = animation_speed

        # The construction function of Canvas
        Canvas.__init__(self, master=tk_instance, width=self._width, height=self._height)

        # Background image
        self._background_image = \
            get_photo_image(image_path=self.image_path, width=self._width, height=self._height, close_after=True)[0]

        # Create a default (static) background
        self._background_default = self.create_image(self._width // 2, self._height // 2, image=self._background_image)
        # Canvas.create_image(x, y, anchor, image)
        # default anchor is CENTER, which means the CENTER point of iamge would be placed at x, y (here, center)
        # return id of that image

        # Create dynamic background
        self._background.append(self.create_image(self._width // 2, self._height // 2, image=self._background_image))
        self._background.append(
            self.create_image(self._width + (self._width // 2), self._height // 2, image=self._background_image))

    def run(self):
        """
        Activate background animation
        """

        if not self._stop:
            self.move(self._background[0], -10, 0)
            self.move(self._background[1], -10, 0)
            # Canvas.move(PhotoImage, x, y) move PhotoImage x indent along x-axis and y indent along y-axis
            self.tag_lower(self._background[0])
            self.tag_lower(self._background[1])
            self.tag_lower(self._background_default)
            # self.tag_lower move the object to the lower level of canvas. 将图片移到最底下的图层 ??

            if self.bbox(self._background[0])[2] <= 0:
                # Delete the image that left beyond the vision
                self.delete(self._background[0])
                self._background.remove(self._background[0])

                width = self.bbox(self._background[0])[2] + self._width // 2
                self._background.append(self.create_image(width, self._height // 2, image=self._background_image))

            # execute this function every period of time
            self.after(self.animation_speed, self.run)

    def reset(self):
        """
        Reset the background
        """

        # delete all items in canvas
        self.delete("all")

        self._stop = False

        # Remove all items from list - self._background
        self._background.clear()

        # Redo create background
        self._background_default = self.create_image(self._width // 2, self._height // 2, image=self._background_image)

        self._background.append(self.create_image(self._width // 2, self._height // 2, image=self._background_image))
        self._background.append(
            self.create_image(self._width + (self._width // 2), self._height // 2, image=self._background_image))

    def stop(self):
        self._stop = True

    def resume(self):
        self._stop = False

    def get_background_id(self):
        """
        Return backgrounds' ID in order to ignore collision with them
        """
        return [self._background_default, *self._background]


#!/bin/bash

def get_cases(source_df, country, column="Country/Region"):
    import pandas as pd

    out = source_df[source_df[column] == country].iloc[:,4:].T
    out.columns = ["{}_cases".format(country)]
    return out.reindex(pd.to_datetime(out.index)).iloc[:,0]

def prepare_cases(cases, winsize, cases_cumulative=False):

    if cases_cumulative:
        new_cases = cases.diff()
    else:
        new_cases = cases

    smoothed = new_cases.rolling(winsize,
        win_type='gaussian',
        min_periods=1,
        center=True).mean(std=2).round()

    zeros = smoothed.index[smoothed.eq(0)]
    if len(zeros) == 0:
        idx_start = 0
    else:
        last_zero = zeros.max()
        idx_start = smoothed.index.get_loc(last_zero) + 1
    smoothed = smoothed.iloc[idx_start:]
    original = new_cases.loc[smoothed.index]

    return original, smoothed

def get_posteriors(sr, winsize=7,
                   min_periods=1,
                   R_T_MAX = 12,
                   GAMMA=1/4):
    import numpy as np
    import pandas as pd
    from scipy import stats as sps

    # We create an array for every possible value of Rt.
    r_t_range = np.linspace(0, R_T_MAX, R_T_MAX*100+1)

    # Compute the Poisson lambdas for each Rt.
    lam = sr[:-1].values * np.exp(GAMMA * (r_t_range[:, None] - 1))

    # Note: if you want to have a Uniform prior you can use the following line instead.
    # I chose the gamma distribution because of our prior knowledge of the likely value
    # of R_t.

    # prior0 = np.full(len(r_t_range), np.log(1/len(r_t_range)))
    prior0 = np.log(sps.gamma(a=3).pdf(r_t_range) + 1e-14)

    likelihoods = pd.DataFrame(
        # Short-hand way of concatenating the prior and likelihoods
        data = np.c_[prior0, sps.poisson.logpmf(sr[1:].values, lam)],
        index = r_t_range,
        columns = sr.index)

    # Perform a rolling sum of log likelihoods. This is the equivalent
    # of multiplying the original distributions. Exponentiate to move
    # out of log.
    posteriors = likelihoods.rolling(winsize,
                                     axis=1,
                                     min_periods=min_periods).sum()
    posteriors = np.exp(posteriors)

    # Normalize to 1.0
    posteriors = posteriors.div(posteriors.sum(axis=0), axis=1)

    return posteriors

def plot_posteriors(posteriors):

    ax = posteriors.plot(title=f'{COUNTRY} - Daily Posterior for $R_t$',
               legend=False,
               lw=1,
               c='k',
               alpha=.3,
               xlim=(0.4,4))

    ax.set_xlabel('$R_t$');

# Note that this takes a while to execute - it's not the most efficient algorithm
def highest_density_interval(pmf, p=.95):
    import pandas as pd
    import numpy as np

    # If we pass a DataFrame, just call this recursively on the columns
    if(isinstance(pmf, pd.DataFrame)):
        return pd.DataFrame([highest_density_interval(pmf[col]) for col in pmf],
                            index=pmf.columns)

    cumsum = np.cumsum(pmf.values)
    best = None
    for i, value in enumerate(cumsum):
        for j, high_value in enumerate(cumsum[i+1:]):
            if (high_value-value > p) and (not best or j<best[1]-best[0]):
                best = (i, i+j+1)
                break

    low = pmf.index[best[0]]
    high = pmf.index[best[1]]
    return pd.Series([low, high], index=['Low', 'High'])

def get_data_for_rt_plot(posteriors):
    import pandas as pd

    hdis = highest_density_interval(posteriors)

    most_likely = posteriors.idxmax().rename('ML')

    # Look into why you shift -1
    result = pd.concat([most_likely, hdis], axis=1)
    result = result.reindex(result.index.rename("date"))

    return result

def process_data(new_cases, winsize, cases_cumulative=False):
    original, smoothed = prepare_cases(new_cases,
                                       winsize=winsize,
                                       cases_cumulative=cases_cumulative)

    posteriors = get_posteriors(smoothed.dropna(), winsize=winsize)

    group_result = get_data_for_rt_plot(posteriors)

    return {'raw':original,
            'smoothed': smoothed,
            'rt': group_result}

def plot_rt(result, ax, COUNTRY):
    import numpy as np
    import pandas as pd

    from matplotlib import pyplot as plt
    from matplotlib.dates import date2num
    from matplotlib import dates as mdates
    from matplotlib import ticker
    from matplotlib.colors import ListedColormap
    from scipy.interpolate import interp1d

    ax.set_title(f"{COUNTRY}")

    # Colors
    ABOVE = [1,0,0]
    MIDDLE = [1,1,1]
    BELOW = [0,0,0]
    cmap = ListedColormap(np.r_[
        np.linspace(BELOW,MIDDLE,25),
        np.linspace(MIDDLE,ABOVE,25)
    ])
    color_mapped = lambda y: np.clip(y, .5, 1.5)-.5

    index = result['ML'].index.get_level_values('date')
    values = result['ML'].values

    # Plot dots and line
    ax.plot(index, values, c='k', zorder=1, alpha=.25, label=COUNTRY)
    ax.scatter(index,
               values,
               s=40,
               lw=.5,
               c=cmap(color_mapped(values)),
               edgecolors='k', zorder=2)

    # Aesthetically, extrapolate credible interval by 1 day either side
    lowfn = interp1d(date2num(index),
                     result['Low'].values,
                     bounds_error=False,
                     fill_value='extrapolate')

    highfn = interp1d(date2num(index),
                      result['High'].values,
                      bounds_error=False,
                      fill_value='extrapolate')

    extended = pd.date_range(start=index[0],
                             end=index[-1]+pd.Timedelta(days=1))

    ax.fill_between(extended,
                    lowfn(date2num(extended)),
                    highfn(date2num(extended)),
                    color='k',
                    alpha=.1,
                    lw=0,
                    zorder=3)

#     ax.axhline(1.0, c='k', lw=1, label='$R_t=1.0$', alpha=.25);

    # Formatting
    ax.xaxis.set_major_locator(mdates.MonthLocator())
    ax.xaxis.set_major_formatter(mdates.DateFormatter('%b'))
    ax.xaxis.set_minor_locator(mdates.DayLocator())

    ax.yaxis.set_major_locator(ticker.MultipleLocator(1))
    ax.yaxis.set_major_formatter(ticker.StrMethodFormatter("{x:.1f}"))
    ax.yaxis.tick_right()
    ax.spines['left'].set_visible(False)
    ax.spines['bottom'].set_visible(False)
    ax.spines['right'].set_visible(False)
    ax.margins(0)
    ax.grid(which='major', axis='y', c='k', alpha=.1, zorder=-2)
    ax.margins(0)


"""String field class & utilities."""
from gettext import gettext as _
from re import compile as re_compile
from typing import Any
from typing import Optional
from typing import Pattern

from pofy.core.constants import UNDEFINED
from pofy.core.errors import ErrorCode
from pofy.core.interfaces import ILoadingContext
from pofy.core.validation import ValidateCallback
from pofy.fields.base_field import ScalarField

class StringField(ScalarField):
    """String YAML object field."""

    def __init__(
        self,
        required: bool = False,
        validate: Optional[ValidateCallback] = None,
        pattern: Optional[str] = None
    ):
        """Initialize string field.

        Args:
            required: See BaseField constructor.
            validate: See BaseField constructor.
            pattern: Pattern the deserialized strings should match. If defined
                     and the string doesn't match, a VALIDATION_ERROR will be
                     raised.

        """
        super().__init__(required=required, validate=validate)
        self._pattern_str: Optional[str] = None
        self._pattern: Optional[Pattern[str]] = None

        if pattern is not None:
            assert isinstance(pattern, str), \
                _('pattern must be a string.')
            self._pattern_str = pattern
            self._pattern = re_compile(pattern)

    def _convert(self, context: ILoadingContext) -> Any:
        value = context.current_node().value

        if self._pattern is not None and not self._pattern.match(value):
            context.error(
                ErrorCode.VALIDATION_ERROR,
                _('Value {} doesn\'t match required pattern {}'),
                value,
                self._pattern_str
            )
            return UNDEFINED

        return value


#Projeto para praticar com python - Project to practice with python
#DESPERTADOR - ALARM CLOCK
from tkinter import *
import datetime
import time
import winsound

def alarm(alarm_time):
    while True: #Hora atual e a data
        time.sleep(1)
        current = datetime.datetime.now()
        now= current.strftime("%H:%M:%S")
        date = current.strftime("%d/%m/%Y")
        print(f'Data definida: {date}')
        print(now)
        if now == alarm_time:
            print("Esta na hora de acordar!!!")

        winsound.PlaySound("galo.wav", winsound.SND_ASYNC)#Colocando o som do alarme
        break

def actual():
    alarm_time = f"{hour.get()} : {min.get()} : {sec.get()}"
    alarm(alarm_time)


import utils
import scraper
from tqdm import tqdm

song_list = []
with open(f'{utils.get_project_root()}/data/processed/overview.csv', 'r') as file:
    for line in file:
        song_list.append((line.split('|')))

for entry in tqdm(song_list):
    read_path = (
        f'{utils.get_project_root()}/data/raw/artists/{entry[0]}/{entry[1]}.html')
    write_path = f'{utils.get_project_root()}/data/processed/list-of-lyrics.txt'
    lyrics = scraper.extract_lyrics(read_path)

    file = open(write_path, 'a')
    file.write(f'{entry[0]}|{entry[1]}|{lyrics}\n')
    file.close()


"Code to check that a User Name meet certain criterias before being accepted"
"""Criterias:
1. username must be at least 2 characters long.
2. It can begin with an alphabet or number but must end with a number

"""
import re
class Users:
    def UserID(self):
        box = []
        username = input("Please insert your Username in the right format: ")
        pattern = '[a-zA-Z0-9]+\d$'
        x = re.findall(pattern, username, re.IGNORECASE)
        box.append(username)

        if x == box:
            print("Username is valid")
        if x!=box:
            print("Username not valid, Try again")
            print("Your username must start with at least a string and end with a number")
usersname=Users()
print("Test 1: ")
usersname.UserID()
# Test 2
print("Test 2: ")
usersname.UserID()
print("Test 3: ")
usersname.UserID()
print("Test 4: ")
usersname.UserID()


if __package__ is None:
    import sys
    sys.path.insert(1, "../../")
    sys.path.insert(1, "../")
    import MVC
    __package__ = "MVC.view"

import PyQt4.QtGui

from ..common.interfaces import iview

import _qt.MainWindow

class QtView(iview.IView):
    def __init__(self, *args, **kwargs):
        super(QtView, self).__init__(*args, **kwargs)
        self.ctl = None

    def setController(self, controller):
        self.ctl = controller

    def run(self):
        app = PyQt4.QtGui.QApplication(sys.argv)
        form = _qt.MainWindow.MainWindow(controller = self.ctl)
        form.show()
        app.exec_()

if __name__ == "__main__":
    v = QtView()
    v.run()


#.-*-.coding:.utf-8.-*-
#.__author__.=."HaoPeng"
#.Date:.2019/9/17

import configparser

def get_config(config_file):
    parser = configparser.ConfigParser()
    parser.read(config_file)
    _conf_ints = [(k, int(v)) for k, v in parser.items('ints')]
    _conf_floats = [(k, int(v)) for k, v in parser.items('floats')]
    _conf_strings = [(k, int(v)) for k, v in parser.items('strings')]
    return dict(_conf_ints + _conf_floats + _conf_strings)


smallPoint = 5
largePoint = 100

def setup():
    size(320, 600)
    global elka,ukr,sng
    elka = loadImage("elka.png")
    ukr = loadImage("ukrr.png")
    sng=loadImage("sng.png")
    imageMode(CENTER)
    noStroke()
    background(255)
    image(elka,width/2-5,height/2-48)

def draw():
    for i in range(0,500):
        pointillize = map(0, 0, width, smallPoint, largePoint)
        x = int(random(ukr.width))
        y = int(random(ukr.height))
        pix = ukr.get(x, y)
        fill(pix, 250)
        ellipse(x, y, pointillize, pointillize)
    translate(0,425)
    for i in range(0,500):
        pointillize = map(0, 0, width, smallPoint, largePoint)
        a = int(random(sng.width))
        b = int(random(sng.height))
        pix = sng.get(a, b)
        fill(pix, 250)
        ellipse(a, b, pointillize, pointillize)


from imblearn.over_sampling import SMOTE
from sklearn import datasets
from sklearn.datasets import load_wine
import pandas as pd
from xgboost import XGBRFClassifier
from sklearn.model_selection import train_test_split
import time
import warnings
from xgboost.sklearn import XGBClassifier
warnings.filterwarnings('ignore')
from icecream import ic
from sklearn.preprocessing import StandardScaler

datasets = pd.read_csv('../_data/wine/winequality-white.csv', index_col=None, header=0, sep=';')

datasets = datasets.values

x = datasets[:,:11]
y = datasets[:,11]

# ic(x.shape, y.shape) # x.shape: (178, 13), y.shape: (178,)

ic(pd.Series(y).value_counts())

'''
6.0    2198
5.0    1457
7.0     880
8.0     175
4.0     163
3.0      20
9.0       5
'''

#############################################
##### 라벨 통합
#############################################

print("="*50)

for index, value in enumerate(y): # 인덱스와 밸류 반환
    if value == 9 :
        y[index] = 8
    elif value == 8:
        y[index] = 8
    elif value == 7:
        y[index] = 6
    elif value == 6:
        y[index] = 6
    elif value == 5:
        y[index] = 5
    elif value == 4:
        y[index] = 5
    elif value == 3:
        y[index] = 5

ic(pd.Series(y).value_counts())

'''
6.0    2198
5.0    1457
7.0     880
8.0     180
4.0     163
3.0      20
'''

x_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.8, shuffle=True, random_state=98, stratify=y)
# stratify: class 비율(ratio)을 train / validation에 유지(한 쪽에 쏠려서 분배되는 것을 방지합니다)
# 이 옵션을 지정해 주지 않고 classification 문제를 다룬다면, 성능의 차이가 많이 날 수 있음

scaler = StandardScaler()
x_train = scaler.fit_transform(x_train)
x_test = scaler.transform(x_test)

ic(pd.Series(y_train).value_counts())

'''
6.0    1648
5.0    1093
7.0     660
8.0     131
4.0     122
3.0      15
9.0       4
'''

model = XGBClassifier(n_jobs=-1)
model.fit(x_train, y_train, eval_metric='mlogloss')

score = model.score(x_test, y_test)
ic(score) # score: 0.6587755102040816

######################################### smote 적용 #########################################
print("="*40,'smote 적용',"="*40)

smote = SMOTE(random_state=77) # k_neighbors가 적어지면 성능이 떨어짐

start = time.time()
x_smote_train, y_smote_train = smote.fit_resample(x_train, y_train) # 적은 데이터들을 가장 큰 데이터에 맞춰서 증폭
end = time.time() - start

print("걸린시간:", end)
ic(pd.Series(y_smote_train).value_counts())

'''
6.0    1648
5.0    1648
4.0    1648
9.0    1648
8.0    1648
7.0    1648
3.0    1648
'''

ic(x_smote_train.shape, y_smote_train.shape) # (159, 13), y_smote_train.shape: (159,)

print("smote 전: ", x_train.shape, y_train.shape)
print("smote 후: ", x_smote_train.shape, y_smote_train.shape)
print("smote 전 레이블 값 분포: \n", pd.Series(y_train).value_counts())
print("smote 후 레이블 값 분포: \n", pd.Series(y_smote_train).value_counts())

model2 = XGBClassifier(n_jobs=-1)

model2.fit(x_smote_train, y_smote_train, eval_metric='mlogloss')

score2 = model2.score(x_test, y_test)
ic(score2)
'''
9 -> 8 score2: 0.6334693877551021

9 -> 8, 3 -> 4 0.626938775510204

0.6563265306122449

'''


__author__ = 'lusisi'
import bisect
class Solution(object):
    def lengthOfLIS(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        cl = []
        for n in nums:
            # i = findhigher(cl,n)
            i = bisect.bisect_left(cl,n) #find the index higher than n
            if i >= len(cl):
                cl.append(n)
            else:
                cl[i] = n if cl[i]>n else cl[i]
        return len(cl)

def findhigherLinear(cl,n):
    for i in xrange(len(cl)):
        if cl[i]>=n:
            return i
    return len(cl)

'''
for sorted list, binear search to find the index i where cl[i]>n, cl[i-1]<=n
bisect_left
'''
def findhigher(cl,n):
    st = 0
    ed = len(cl)-1
    while st<=ed:
        mid = (st+ed)/2
        if cl[mid]<n:
            st = mid+1
        else:
            ed = mid-1
    return st


from src.Ressources import postRessources, pingRessources
from fastapi import FastAPI, status, Request
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse

app = FastAPI()

@app.exception_handler(RequestValidationError)
async def validation_exception_handler(request: Request, exc: RequestValidationError):
    message: str = None

    if ("tags" in str(exc)):
        message = "Tags parameter is required"
    elif ("sortBy" in str(exc)):
        message = "sortBy parameter is invalid"
    else:
        message = "direction parameter is invalid"

    return JSONResponse(status_code=status.HTTP_400_BAD_REQUEST, content= {"error": message})

app.include_router(postRessources.posts_router)
app.include_router(pingRessources.ping_router)


def Exit(): # 종료 함수
    print(0)
    exit()

def check1(arr): # 사다리 확인
    count=0
    for n in range(1, N+1):
        newN=n
        for h in range(1, H+1):
            if arr[h][newN]==0 or arr[h][newN]==-1: continue
            newN=arr[h][newN] # 새로운 값 넣기
        if n!= newN: #끝과 끝이 다르다면,
            count+=1 #카운팅

    if count==0:
        return True
    return False

def wall(cnt):
    global ans

    if cnt!=0 and check1(arr): # 가로선 개수가 0이 아니고, 사다리 확인 시 true인 경우,
        ans=min(cnt, ans) # 최소값 찾기

    if cnt==3: #가로선 개수가 3개라면, 종료
        return

    for n in range(1, N): # 1 ~ (N-1)
        for h in range(1, H+1): # 1 ~ H
            if (arr[h][n]!=0 or arr[h][n+1]!=0):continue # 0이 아니라면, 돌아감

            arr[h][n]=n+1 # 가로선 설정
            arr[h][n+1]=n # 가로선 설정

            wall(cnt+1) # 가로선 개수 증가

            arr[h][n]=0 # 가로선 해제
            arr[h][n+1]=0 # 가로선 해제

""" 0. 입력받기 """
N, M, H=map(int, input().split()) # 세로선 개수, 가로선 개수, 높이 개수
if M==0: Exit() # 가로선 개수가 0이라면, 종료
arr = [[0]*(N+1) for _ in range(H+1)] # 사다리 표기(0인덱스 사용하지 않음)

""" 1. 기존 사다리 저장 """
for _ in range(M):
    i, j = map(int, input().split())
    arr[i][j]=j+1 # j+1 행값 넣음
    arr[i][j+1]=j # j 행값 넣음
    if 1<=(j-1) and arr[i][j-1]==0: arr[i][j-1]=-1 # 가로선이 연장하지 않기 위해 금지 표기
    if (j+2)<=N and arr[i][j+2]==0: arr[i][j+2]=-1 # 가로선이 연장하지 않기 위해 금지 표기
if check1(arr): Exit() # 사다리 확인 후, true라면 종료

""" 2. 사다리 확인 """
ans=4 # 정답이 4이상으로 나올 수 없기 때문에
wall(0) # 가로선 설정 및 해제
if ans==4: # 최소값이 4라면,
    print(-1) # 가로선을 놓아도 답이 될 수 없다고 판단하여 -1 출력
else:
    print(ans) # 가로선을 놓아서 답이 된다면, 놓은 가로선 개수 출력


from keras.callbacks import Callback
import warnings
try:
    import matplotlib.pyplot as plt
except ImportError:
    plt = None

class Plotter(Callback):
    """
    Plots keras training metric during training
    :param monitor: The metric to monitor and plot. Set to "loss" to plot the loss. Defaults to plotting the loss.
    :param scale: The scale to plot with. Options are "linear" and "log". Defaults to linear.
    :param plot_during_train: Will plot the metric during training of model
    :param save_to_file: Saves the plot to a file
    :param block_on_end: Blocks running code at the end of training.
    """

    def __init__(self, monitor="loss", scale='linear', plot_during_train=True, save_to_file=None, block_on_end=True):
        super().__init__()
        if plt is None:
            raise ValueError("Must be able to import Matplotlib to use the Plotter.")
        self.scale = scale
        self.monitor = monitor
        self.plot_during_train = plot_during_train
        if not self.plot_during_train:
            raise NotImplementedError("Turning off plotting during training is not implemented yet")
        self.save_to_file = save_to_file
        self.block_on_end = block_on_end
        plt.ion()
        self.fig = plt.figure()
        self.title = "{} per Epoch".format(self.monitor)
        self.xlabel = "Epoch"
        self.ylabel = self.monitor
        self.ax = self.fig.add_subplot(111, title=self.title,
                                       xlabel=self.xlabel, ylabel=self.ylabel)
        self.ax.set_yscale(self.scale)
        self.x = []
        self.y_train = []
        self.y_val = []

    def on_train_end(self, logs={}):
        plt.ioff()
        if self.block_on_end:
            plt.show()
        return

    def on_epoch_end(self, epoch, logs={}):
        # Set up the plot
        self.ax.clear()
        self.fig.suptitle(self.title)
        self.ax.set_yscale(self.scale)

        train_score = logs.get(self.monitor)
        val_score = logs.get("val_" + self.monitor)
        # Some error checking
        if train_score is None:
            warnings.warn("Monitoring metric {monitor} cannot be found, cannot plot".format(monitor=self.monitor))
            return

        # Do the train plotting
        self.x.append(len(self.x))
        self.y_train.append(train_score)
        self.ax.plot(self.x, self.y_train, 'b-')

        # Check if we have validation scores to plot
        if val_score is None:
            warnings.warn("No validation metric {monitor} can be found, cannot plot validation scores".format(monitor=self.monitor))

        else:
            # Do the val plotting
            self.y_val.append(val_score)
            self.ax.plot(self.x, self.y_val, 'g-')

        # Save file and draw
        if self.save_to_file is not None:
            self.fig.savefig(self.save_to_file)
        self.fig.canvas.draw()
        return


import sklearn.datasets
import sklearn.linear_model
import numpy.random
import numpy.linalg
import matplotlib.pyplot

if __name__ == "__main__":
# Load boston dataset
    boston = sklearn.datasets.load_boston()

# Split the dataset with sampleRatio
sampleRatio = 0.5
n_samples = len(boston.target)
sampleBoundary = int(n_samples * sampleRatio)

# Shuffle the whole data
shuffleIdx = list(range(n_samples))
numpy.random.shuffle(shuffleIdx)

# Make the training data
train_features = boston.data[shuffleIdx[:sampleBoundary]]
train_targets = boston.target[shuffleIdx [:sampleBoundary]]

# Make the testing data
test_features = boston.data[shuffleIdx[sampleBoundary:]]
test_targets = boston.target[shuffleIdx[sampleBoundary:]]

# Train
linearRegression = sklearn.linear_model.LinearRegression()
linearRegression.fit(train_features, train_targets)

# Predict
predict_targets = linearRegression.predict(test_features)

# Evaluation
n_test_samples = len(test_targets)
X = range(n_test_samples)
error = numpy.linalg.norm(predict_targets - test_targets, ord = 1) / n_test_samples
print ("Ordinary Least Squares (Boston) Error: %.2f" %(error))
# Draw
matplotlib.pyplot.plot(X, predict_targets, 'r--*', label = 'Predict Price')
matplotlib.pyplot.plot(X, test_targets, 'g:', label='True Price')
legend = matplotlib.pyplot.legend()
matplotlib.pyplot.title("Ordinary Least Squares (Boston)")
matplotlib.pyplot.ylabel("Price")
matplotlib.pyplot.savefig("Ordinary Least Squares (Boston).png", format='png')
matplotlib.pyplot.show()


import random

import numpy as np
import torch
import torch.backends.cudnn as cudnn

from src.utils import BaseNet, cprint, to_variable
from src.utils import rms
from src.probability import homo_Gauss_mloglike

def ensemble_predict(net, savefiles, x, return_model_std=False, return_individual_functions=False,  to_cpu=False):
    mean_vec = []
    noise_std_vec = []
    for file in savefiles:
        net.load(file, to_cpu=to_cpu)
        mu, noise_std = net.predict(x, return_model_std=False)  # want full std = noise std
        mean_vec.append(mu.data)
        noise_std_vec.append(noise_std.data)
    mean_vec = torch.stack(mean_vec, dim=0)
    std_vec = torch.stack(noise_std_vec, dim=0)

    if return_individual_functions:
        return mean_vec, std_vec
    else:
        mean = mean_vec.mean(dim=0)
        model_var = mean_vec.var(dim=0)
        if len(savefiles) == 0:
            model_var = torch.zeros_like(model_var)

        noise_var = std_vec.pow(2).mean(dim=0)

        if return_model_std:
            return mean, model_var.pow(0.5)
        else:
            pred_std = (model_var + noise_var).pow(0.5)
            return mean, pred_std

class regression_baseline_net(BaseNet):
    def __init__(self, model, N_train, lr=1e-2, momentum=0.5, cuda=True, schedule=None, seed=None,
                 weight_decay=0, MC_samples=10, Adam=False):
        super(regression_baseline_net, self).__init__()

        cprint('y', 'DUN learnt with marginal likelihood categorical output')
        self.lr = lr
        self.momentum = momentum
        self.Adam = Adam
        self.weight_decay = weight_decay
        self.MC_samples = MC_samples
        self.model = model
        self.cuda = cuda
        self.seed = seed

        self.f_neg_loglike = homo_Gauss_mloglike(self.model.output_dim, None)
        self.f_neg_loglike_test = self.f_neg_loglike

        self.N_train = N_train
        self.create_net()
        self.create_opt()
        self.schedule = schedule  # [] #[50,200,400,600]
        if self.schedule is not None and len(self.schedule) > 0:
            self.make_scheduler(gamma=0.1, milestones=self.schedule)
        self.epoch = 0

    def create_net(self):
        if self.seed is not None:
            random.seed(self.seed)
            np.random.seed(self.seed)
            torch.manual_seed(self.seed)
            if self.cuda:
                torch.cuda.manual_seed(self.seed)
        if self.cuda:
            self.model.cuda()
            self.f_neg_loglike.cuda()

            cudnn.benchmark = True
        print('    Total params: %.2fM' % (self.get_nb_parameters() / 1000000.0))

    def create_opt(self):
        param_list = list(self.model.parameters()) + list(self.f_neg_loglike.parameters())
        if not self.Adam:
            self.optimizer = torch.optim.SGD(param_list, lr=self.lr, momentum=self.momentum,
                                             weight_decay=self.weight_decay)
        else:
            self.optimizer = torch.optim.Adam(param_list, lr=self.lr, weight_decay=self.weight_decay)

    def fit(self, x, y):
        """Standard training loop: MC dropout and Ensembles"""
        self.model.train()
        x, y = to_variable(var=(x, y), cuda=self.cuda)
        self.optimizer.zero_grad()

        mean = self.model.forward(x)
        NLL = self.f_neg_loglike(mean, y).mean(dim=0)
        NLL.backward()
        self.optimizer.step()

        err = rms(mean, y).item()
        return -NLL.data.item(), NLL.data.item(), err

    def eval(self, x, y):
        self.model.eval()
        x, y = to_variable(var=(x, y), cuda=self.cuda)

        mean, model_std = self.model.forward_predict(x, self.MC_samples)
        mean_pred_loglike = self.f_neg_loglike(mean, y, model_std=model_std).mean(dim=0).data
        err = rms(mean, y).item()
        return mean_pred_loglike.item(), err

    def predict(self, x, Nsamples=10, return_model_std=False):
        self.model.eval()
        x, = to_variable(var=(x,), cuda=self.cuda)
        mean, model_std = self.model.forward_predict(x, Nsamples)
        if return_model_std:
            return mean.data, model_std  # not data in order to take integer from sgd
        else:
            pred_std = (model_std**2 + self.f_neg_loglike.log_std.exp()**2).pow(0.5)
            return mean.data, pred_std.data

class regression_baseline_net_VI(regression_baseline_net):
    def __init__(self,  model, N_train, lr=1e-2, momentum=0.5, cuda=True, schedule=None, seed=None,
                 weight_decay=0, MC_samples=10, train_samples=3, Adam=False):
        super(regression_baseline_net_VI, self).__init__(model=model, N_train=N_train, lr=lr, momentum=momentum,
                                                         cuda=cuda, schedule=schedule, seed=seed, weight_decay=0,
                                                         MC_samples=MC_samples, Adam=Adam)
        # We fix weight decay to be 0 here as we are using KL divergence.
        self.train_samples = train_samples

    def fit(self, x, y):
        """Optimise stchastically estimated marginal joint of parameters and weights"""
        self.model.train()
        x, y = to_variable(var=(x, y), cuda=self.cuda)
        self.optimizer.zero_grad()

        sample_means = self.model.forward(x, self.train_samples)

        batch_size = x.shape[0]
        repeat_dims = [self.train_samples] + [1 for i in range(1, len(y.shape))]  # Repeat batchwise without interleave
        y_expand = y.repeat(*repeat_dims)  # targets are same across acts -> interleave
        sample_means_flat = sample_means.view(self.train_samples * batch_size, -1)  # flattening results in batch_n changing first
        E_NLL = self.f_neg_loglike(sample_means_flat, y_expand).view(self.train_samples, batch_size).mean(dim=(0,1))

        minus_E_ELBO = E_NLL + self.model.get_KL() / self.N_train
        minus_E_ELBO.backward()
        self.optimizer.step()
        err = rms(sample_means.mean(dim=0), y).item()
        return -minus_E_ELBO.data.item(), E_NLL.data.item(), err


from bs4 import BeautifulSoup
from urllib.request import urlopen
import re

class JobAd2:
    """Create BeautifulSoup object from www.cv.lv job-ad url. Need to provide
    BeautifulSoup object of search result url and url of the job-ad itself.
    Using object attributes listed below retrieve various details of job-ad:
     - company: return name of company posting its vacancy
     - deadline: return job-ad's application deadline
     - position: return position
     - post_date: return posting date of job-ad
     - ref_no: return reference number of job-ad
     - url: return url of job-ad
     - views: return number of times job-ad has been viewed
     """
    def __init__(self, master_soup, url):

        self.__msoup = master_soup
        self.url = "http:" + url
        self.__url_lst = self.url.split('/')
        self.__html = urlopen(self.url).read()
        self.__soup = BeautifulSoup(self.__html, 'html.parser')

        self.company = self.__get_company()
        self.deadline = self.__get_expi_date()
        self.position = self.__get_position()
        self.post_date = self.__get_post_date()
        self.ref_no = self.__get_ref()
        self.views = self.__get_views()

    def __get_company(self):
        """Return name of the company offering vacancy"""
        comp_dict = {"class": re.compile("jobadCompanyName")}
        comp_tag = self.__soup.find(attrs=comp_dict)

        # in case no tag can be returned extract company name from url
        if comp_tag == None:
            comp_str = self.__url_lst[-2]
            comp_lst = comp_str.split('-')
            return (' '.join(comp_lst)).upper()

        company = ''.join(comp_tag.find(itemprop=re.compile("name")).contents)
        company = company.strip()

        return company

    def __get_expi_date(self):
        """Return expiration date of the job-ad"""
        dead_dict = {"class": re.compile("jobadDeadline")}
        dead_tag = self.__soup.find(attrs=dead_dict)
        if dead_tag == None:
            return None
        deadline = ''.join(dead_tag.contents)
        deadline = deadline.strip()

        return deadline

    def __get_position(self):
        """Return position offered in the job-ad"""
        pos_dict = {"class": re.compile("jobadPosition")}
        pos_tag = self.__soup.find(attrs=pos_dict)

        # in case no tag can be returned extract position from url
        if pos_tag == None:
           pos_str = self.__url_lst[-1]
           pos_lst = pos_str.split('-')
           del pos_lst[-1]
           return (' '.join(pos_lst)).upper()

        pos = ''.join(pos_tag.find(itemprop=re.compile("title")).contents)
        pos = pos.strip()

        return pos

    def __get_post_date(self):
        """Return posting date of the job-ad"""
        date_str = re.compile("datePosted")
        post_tag = self.__soup.find(itemprop=date_str)
        if post_tag == None:
            return None
        post_date = ''.join(post_tag.contents)
        post_date = post_date.strip()

        return post_date

    def __get_ref(self):
        """Return reference number of job-ad"""
        ref_text = self.__soup.find(text=re.compile("Sludinājuma numurs"))
        if ref_text == None:
            ref_text = self.__soup.find(text=re.compile("Reference number"))

        # in case no tags can be returned extract reference number from url
        if ref_text == None:
            ref_str = self.__url_lst[-1]
            ref_lst = ref_str.split('-')
            ref = ''.join([n for n in ref_lst[-1] if (n >= '0' and n <= '9')])
            return "CVO-" + ref + "-LV"

        ref = ''.join([n for n in ref_text if (n >= '0' and n <= '9')])
        ref = "CVO-"+ref+"-LV"
        ref = ref.strip()

        return ref

    def __get_views(self):
        """Return number of times job-ad has been viewed. In case no views can
        be found, return None
        """
        ref_nr = ''.join([n for n in self.__get_ref() if (n >= '0' and n <= '9')])
        views_tag = self.__msoup.find('tr', id=re.compile(str(ref_nr)))
        if views_tag == None:
            return None
        else:
            views = views_tag.find(text=re.compile("Skatījumi"))
            views = str(''.join([n for n in views if (n >= '0' and n <= '9')]))

        return int(views)

    def update(self):
        """Update all data"""
        self.company = self.__get_company()
        self.deadline = self.__get_expi_date()
        self.position = self.__get_position()
        self.post_date = self.__get_post_date()
        self.ref_no = self.__get_ref()
        self.views = self.__get_views()


import random

import time

answer_list=[]
used_letters=[]
totalTime = .5
word_list = ['DOG','CAT']
bad_names = ['Pumpkin Spice', 'Cup Cake', ' Fart Breath', 'Dummy']
answer = random.choice(word_list)
new_name = random.choice(bad_names)
name = input(' Who dares challange me?  ' ).upper()

time.sleep(totalTime)
print(f'ok { name } lets play some hangman  \n \n ' )
time.sleep(totalTime)
print(f'You know what, I dont like the name { name }\n \n So I will now call you { new_name.upper() }  \n\n ' )
time.sleep(totalTime)
print(f'The answer has { len(answer) } letters \n\n ' )
time.sleep(totalTime)
print(f'The catagory is ANIMALS,     Thats the only hint you will get  \n \n' )
time.sleep(totalTime)
print(f'You Have 5 incorrect  guesses so good luck \n  \n')

display = []
display.extend(answer)
# print(display)

guess = input(f'Pick a letter ====> ').upper()
chances = len(answer) + 3
while chances > 0:

        if guess in answer:
                chances -= 1
                print('LUCKY GUESS  That one is in there >>>>>  ')
        if guess not in answer:
                chances -= 1
                used_letters.append(guess)
                print(f' You have { chances } guesses left' )
                print(f' you have used { used_letters } ' )
else:
        if chances == 0:
                print('Really Dude?')
                print("            I give up dude  \n "
                        "             GAME OVER!!!!          ")


#!/usr/bin/env python3
import sys
from json import load
from os import path

from environs import Env

from app import bot
from app.dependencies import Dependencies

env = Env()
basedir = path.dirname(__file__)

with open('emoji_to_roles.json') as f:
    emoji_to_role = load(f)

# Read variables from .env && constant configs
env.read_env()

# Load environment and config from BOT_ENV variable name
app_env = env.str('BOT_ENV', 'local')

# Prepare dependencies
inject = Dependencies()
inject.config.from_ini(path.join(basedir, app_env + '.ini'), required=True)
inject.config.inject.config.from_dict({
    'bot_secret':    env.str('DISCORD_BOT_SECRET_KEY'),
    'admin_id':      env.int('DISCORD_BOT_ADMIN_ID'),
    'emoji_to_role': emoji_to_role,
})

inject.wire(modules=[sys.modules['app']])

# Start features :)
bot.run()


#!/usr/bin/env python
import numpy as np

from . import pg_utilities

def grow_chorionic_surface(angle_max, angle_min, fraction, min_length, point_limit,
                           volume, thickness, ellipticity, datapoints, initial_geom, sorv):
    # Calulate axis dimensions of ellipsoid with given volume, thickness and ellipticity
    radii = pg_utilities.calculate_ellipse_radii(volume, thickness, ellipticity)
    z_radius = radii['z_radius']
    x_radius = radii['x_radius']
    y_radius = radii['y_radius']

    # We can estimate the number of elements in the generated model based on the number of data (seed points) to
    #  pre-allocate data arrays.
    est_generation = int(np.ceil(np.log(len(datapoints)) / np.log(2)))
    total_estimated = 0

    for i in range(0, est_generation + 1):
        total_estimated = total_estimated + 2 ** i
    num_elems_old = len(initial_geom["umb_elems"])
    num_nodes_old = len(initial_geom["umb_nodes"])
    num_elems_new = num_elems_old + total_estimated
    num_nodes_new = num_nodes_old + total_estimated
    # Pre-allocation of data arrays
    elem_directions = np.zeros((num_elems_new, 3))
    elem_order = np.zeros((num_elems_new, 3))
    node_loc = np.zeros((num_nodes_new, 4))
    node_loc[0:num_nodes_old][:] = initial_geom["umb_nodes"]
    elems = np.zeros((num_elems_new, 3))
    elems[0:num_elems_old][:] = initial_geom["umb_elems"]
    elem_upstream = np.zeros((num_elems_new, 3))
    elem_upstream[0:num_elems_old][:] = initial_geom['elem_up']
    elem_downstream = np.zeros((num_elems_new, 3))
    elem_downstream[0:num_elems_old][:] = initial_geom['elem_down']

    # local arrays
    nstem = np.zeros((num_elems_new, 2))
    ne_temp = np.zeros(num_elems_new)
    ne_old = np.zeros(1000)
    ld = np.zeros(len(datapoints))
    ld_np = np.zeros(len(datapoints))
    ldtmp1 = np.zeros(len(datapoints))

    numtbsum = 0

    # Calculate the generations for the initial branches
    # Calculate the direction of the initial branches

    for ne in range(0, num_elems_old):
        if elem_upstream[ne][0] == 0.0:  # This is the stem (inlet) vessel
            elem_order[ne][0] = 1
        else:
            ne0 = int(elem_upstream[ne][1])
            elem_order[ne][0] = elem_order[ne0][0] + 1
        node_in = int(elems[ne][1])
        node_out = int(elems[ne][2])
        elem_directions[ne][:] = calc_branch_direction(node_loc[node_out][1:4] - node_loc[node_in][1:4])
    # initialise ne_old (list of old terminals) to list of terminals in current geometry
    parentlist = group_elem_parent_term(0, initial_geom['elem_down'])
    ne_old[0:len(parentlist)] = parentlist
    nt_bns = len(ne_old)  # Curerent number of terminals
    n_elm = nt_bns
    for n in range(0, len(parentlist)):
        nstem[n][0] = ne_old[n]

    # Initialise LD array to map each seed point to a parent branch.
    # For a single parent, all seed points will initially be mapped to
    # it; for multiple parents data_to_mesh is called to calculate
    # the closest parent end-point to each seed point.
    ld = ld + ne_old[0]
    ld_np = ld
    ld = data_to_mesh(ld, datapoints, ne_old, node_loc, elems)

    # Assign temporary arrays
    for nd in range(0, len(datapoints)):
        if ld[nd] != 0:
            ne_min = int(ld[nd])
            nstem[ne_min][1] = nstem[ne_min][1] + 1
            ldtmp1[nd] = ld[nd]

    # Dealing with cases when there are no datapoints assigned with an element
    nt_bns = 0
    for n in range(0, len(parentlist)):
        if nstem[int(parentlist[n])][1] != 0:
            ne_old[nt_bns] = parentlist[n]
            nt_bns = nt_bns + 1
    n_elm = nt_bns
    n_elm_temp = n_elm

    # remove terminal elements with only one data point associated and corresponding data pomt
    # from the group
    for n in range(0, n_elm):
        ne_min = int(ne_old[n])
        if nstem[ne_min][1] < 2:
            for nd in range(0, len(datapoints)):
                ldtmp1[nd] = ld[nd]
                ld[nd] = 0
                ne_old[n] = 0
                n_elm_temp = n_elm_temp - 1
    numtb = 0
    for n in range(0, n_elm):
        if ne_old[n] == 0:
            i = 0
            while (n + i < n_elm) and (ne_old[n + i] == 0):
                i = i + 1
            for m in range(n, n_elm - 1):
                ne_old[m] = ne_old[m + i]
            numtb = numtb + 1
    n_elm = n_elm_temp

    ld_num = 0
    for nd in range(0, len(datapoints)):
        if ld[nd] > 0:
            ld_num = ld_num + 1
    # START OF BIFURCATING DISTRIBUTATIVE ALGORITHM

    print('         gen       #brn       total#       #term      #data')

    # Set initial values for local and global nodes and elements
    ne = num_elems_old - 1  # current maximum element number
    nnod = num_nodes_old - 1  # current maximum node number
    ne_start = ne

    ne_parent = int(parentlist[0])
    ngen = 3
    ne_min = ne

    while n_elm != 0:
    #for ok in range(0,2):
        ngen = ngen + 1  # increment generation from parent
        nt_bns = n_elm
        n_elm = 0
        numzero = 0
        noelem_gen = 0
        max_dist = 0.0

        for m in range(0, nt_bns):
            ne_parent = int(ne_old[m])
            com = mesh_com(ne_parent, ld, datapoints)
            ne_grnd_parent = int(elem_upstream[ne_parent][1])  # Assumes only one parent, true in diverging tree
            np_start = int(elems[ne_parent][2])
            #np_prt_start = int(elems[ne_parent][1])
            #np_grnd_start = int(elems[ne_grnd_parent][1])
            #if elem_downstream[ne_grnd_parent][1] == ne_parent:
            #    if elem_downstream[ne_grnd_parent][2] == 0:
            #        np4 = int(elems[elem_upstream[ne_grnd_parent][1]][1])
            #    else:
            #        np4 = int(elems[elem_downstream[ne_grnd_parent][2]][2])
            #else:
            #    np4 = int(elems[elem_downstream[ne_grnd_parent][1]][2])

            length_parent = dist_two_vectors(node_loc[int(elems[ne_parent][1])][1:4], node_loc[int(elems[ne_parent][2])][1:4])

            # Split the seed points by the plane defined by the parent branch and the com of the
            # seedpoints attached to it
            if sorv is 'surface':
                split_data = data_splitby_xy(ld, datapoints, com, node_loc[np_start][1:3], ne_parent, ne, point_limit)
            else:
                # data_splitby_plane
                print('hello')
            # Check that you are going to grow two branches
            if split_data['ss'][0] and split_data['ss'][1]:
                for n in range(0, 2):
                    com = mesh_com(ne + 1, ld, datapoints)

                    start_node_loc = node_loc[np_start][1:4]
                    length_new = np.linalg.norm(fraction * (com - start_node_loc))
                    if length_new <  min_length:
                        end_node_loc = start_node_loc + min_length * (com - start_node_loc)/np.linalg.norm((com - start_node_loc))
                    else:
                        end_node_loc = start_node_loc + fraction * (com - start_node_loc)
                    if sorv is 'surface':
                        end_node_loc[2] = pg_utilities.z_from_xy(end_node_loc[0], end_node_loc[1], x_radius, y_radius,
                                                                 z_radius)
                    # insert checks that the branches are valid here
                    branch = True
                    if sorv is 'surface':
                        node1=np.array([node_loc[int(elems[ne_parent][1])][1], node_loc[int(elems[ne_parent][1])][2], 0])
                        node2=np.array([start_node_loc[0], start_node_loc[1], 0])
                        node3=np.array([end_node_loc[0], end_node_loc[1], 0])
                        end_node=mesh_check_angle(angle_min,angle_max,node1,node2,node3,ne_parent,ne+1)
                        end_node_loc[0:2] = end_node[0:2]
                        end_node_loc[2] = pg_utilities.z_from_xy(end_node[0],end_node[1],x_radius,y_radius,z_radius)
                    # Create new elements and nodes
                    elems[ne + 1][0] = ne + 1
                    elems[ne + 1][1] = np_start
                    elems[ne + 1][2] = nnod + 1
                    elem_upstream[ne + 1][0] = 1
                    elem_upstream[ne + 1][1] = ne_parent
                    elem_downstream[ne + 1][0] = 0

                    elem_downstream[ne_parent][0] = elem_downstream[ne_parent][0] + 1
                    elem_downstream[ne_parent][int(elem_downstream[ne_parent][0])] = ne + 1

                    node_loc[nnod + 1][0] = nnod + 1
                    node_loc[nnod + 1][1:4] = end_node_loc
                    ne = ne + 1
                    nnod = nnod + 1

                    elem_order[ne][0] = elem_order[ne][0] + 1
                    noelem_gen = noelem_gen + 1 #Only used for runtime output

                    nstem[ne][0] = nstem[ne_parent][0]

                    if branch and split_data['ss'][n]:
                        ne_temp[n_elm] = ne
                        n_elm = n_elm + 1
                    else:
                        numtb = numtb + 1

            else:  # Not ss so no splitting
                # Not enough seed points in the set during the split so ne_parent becomes a terminal branch
                # Find teh closest seed point and remove
                numtb = numtb + 1
                min_dist = 1.0e10
                for nd in range(0, len(datapoints)):
                    if ld[nd] != 0:
                        if ld[nd] == ne + 1:
                            ld[nd] = ne_parent #give back to parent
                        if ld[nd] == ne + 2:
                            ld[nd] = ne_parent
                        dist = dist_two_vectors(datapoints[nd][:], node_loc[int(elems[ne_parent][2])][1:4])
                        if dist < min_dist:
                            if ld[nd] == ne_parent:
                                nd_min = nd
                                min_dist = dist
                ldtmp1[nd_min] = ne_parent
                ld[nd_min] = 0
                ld_num = ld_num - 1

        # .......Copy the temporary list of branches to NE_OLD. These become the
        # .......parent elements for the next branching

        for n in range(0, n_elm):
            ne_old[n] = ne_temp[n]
            nstem[int(ne_old[n])][1] = 0  # initialaw count of data points

        # reallocate datapoints
        ld = data_to_mesh(ld, datapoints, ne_old[0:n_elm], node_loc, elems)

        print('   ' +str(ngen) + '   ' + str(noelem_gen) + '   ' + str(ne) +
              '   ' + str(numtb) + '   ' + str(ld_num) + '   ' + str(
            numtb + ld_num + numtbsum))
        numtbsum = numtbsum + numtb

    elems.resize(ne + 1, 3, refcheck=False)
    elem_upstream.resize(ne + 1, 3, refcheck=False)
    elem_downstream.resize(ne + 1, 3, refcheck=False)
    node_loc.resize(nnod + 1, 4, refcheck=False)

    return {'nodes': node_loc, 'elems': elems, 'elem_up': elem_upstream, 'elem_down': elem_downstream}

def mesh_check_angle(angle_min,angle_max,node1,node2,node3,ne_parent,myno):
    normal_to_plane = np.zeros(3)
    vector_cross_n = np.zeros(3)
    vector1=(node2-node1)
    vector1_u=vector1/np.linalg.norm(node2-node1)
    vector2=(node3-node2)
    vector2_u=vector2/np.linalg.norm(node3-node2)

    if (np.equal(vector1_u,vector2_u)).all():
        node3 [0] = node3[0]*.99
        node3 [1] = node3[1]*1.01
        vector2=node3-node2

    #want to rotate vector 2 wrt vector 1
    angle=pg_utilities.angle_two_vectors(vector1,vector2)

    normal_to_plane [0] = (vector2[1]*vector1[2] - vector2[2]*vector1[1])
    normal_to_plane [1] = (vector2[0]*vector1[2] - vector2[2]*vector1[0])
    normal_to_plane [2] = (vector2[0]*vector1[1] - vector2[1]*vector1[0])

    normal_to_plane_u = normal_to_plane / np.linalg.norm(normal_to_plane)

    vector_cross_n [0] = (vector1[1]*normal_to_plane[2] - vector1[2]*normal_to_plane[1])
    vector_cross_n [1] = (vector1[0]*normal_to_plane[2] - vector1[2]*normal_to_plane[0])
    vector_cross_n [2] = (vector1[0]*normal_to_plane[1] - vector1[1]*normal_to_plane[0])

    dotprod=np.dot(vector2,vector_cross_n)

    if dotprod < 0:
        angle = -1* angle

    if abs(angle) < angle_min:
        # Need to adjust node3 to get a angle equal to  angle_min
        angle0=abs(angle)
        angle_rot=(angle0-angle_min) #amount of angle to add

        #need to rotate around axis normal to the plane that the original and the vector make
        #unit vector normal to plane:
        R=np.zeros((3,3))
        R[0][0] = np.cos(angle_rot) + normal_to_plane_u[0]**2*(1-np.cos(angle_rot))
        R[0][1] = normal_to_plane_u[0]*normal_to_plane_u[1]*(1-np.cos(angle_rot))-normal_to_plane_u[2]*np.sin(angle_rot)
        R[0][2] = normal_to_plane_u[0]*normal_to_plane[2]*(1-np.cos(angle_rot))+normal_to_plane_u[1]*np.sin(angle_rot)
        R[1][0] =normal_to_plane_u[0]*normal_to_plane_u[1]*(1-np.cos(angle_rot))+normal_to_plane_u[2]*np.sin(angle_rot)
        R[1][1] = np.cos(angle_rot) + normal_to_plane_u[1]**2*(1-np.cos(angle_rot))
        R[1][2] = normal_to_plane_u[1]*normal_to_plane_u[2]*(1-np.cos(angle_rot))-normal_to_plane_u[0]*np.sin(angle_rot)
        R[2][0] = normal_to_plane_u[0]*normal_to_plane[2]*(1-np.cos(angle_rot))-normal_to_plane_u[1]*np.sin(angle_rot)
        R[2][1] = normal_to_plane_u[1]*normal_to_plane_u[2]*(1-np.cos(angle_rot))+normal_to_plane_u[0]*np.sin(angle_rot)
        R[2][2] = np.cos(angle_rot) + normal_to_plane_u[2]**2*(1-np.cos(angle_rot))
        nu_vec=np.zeros(3)
        nu_vec [0] = R[0][0]*vector2[0]+R[0][1]*vector2[1]+R[0][2]*vector2[2]
        nu_vec[1] = R[1][0] * vector2[0] + R[1][1] * vector2[1] + R[1][2] * vector2[2]
        nu_vec[2] = R[2][0] * vector2[0] + R[2][1] * vector2[1] + R[2][2] * vector2[2]

        node3 = node2 + nu_vec

    elif abs(angle) > angle_max:
        # Need to adjust node3 to get a angle equal to  angle_max
        angle0=abs(angle)
        angle_rot=(angle0-angle_max) #amount of angle to add

        #need to rotate around axis normal to the plane that the original and the vector make
        #unit vector normal to plane:
        R=np.zeros((3,3))
        R[0][0] = np.cos(angle_rot) + normal_to_plane_u[0]**2*(1-np.cos(angle_rot))
        R[0][1] = normal_to_plane_u[0]*normal_to_plane_u[1]*(1-np.cos(angle_rot))-normal_to_plane_u[2]*np.sin(angle_rot)
        R[0][2] = normal_to_plane_u[0]*normal_to_plane[2]*(1-np.cos(angle_rot))+normal_to_plane_u[1]*np.sin(angle_rot)
        R[1][0] =normal_to_plane_u[0]*normal_to_plane_u[1]*(1-np.cos(angle_rot))+normal_to_plane_u[2]*np.sin(angle_rot)
        R[1][1] = np.cos(angle_rot) + normal_to_plane_u[1]**2*(1-np.cos(angle_rot))
        R[1][2] = normal_to_plane_u[1]*normal_to_plane_u[2]*(1-np.cos(angle_rot))-normal_to_plane_u[0]*np.sin(angle_rot)
        R[2][0] = normal_to_plane_u[0]*normal_to_plane[2]*(1-np.cos(angle_rot))-normal_to_plane_u[1]*np.sin(angle_rot)
        R[2][1] = normal_to_plane_u[1]*normal_to_plane_u[2]*(1-np.cos(angle_rot))+normal_to_plane_u[0]*np.sin(angle_rot)
        R[2][2] = np.cos(angle_rot) + normal_to_plane_u[2]**2*(1-np.cos(angle_rot))

        nu_vec=np.zeros(3)
        nu_vec [0] = R[0][0]*vector2[0]+R[0][1]*vector2[1]+R[0][2]*vector2[2]
        nu_vec[1] = R[1][0] * vector2[0] + R[1][1] * vector2[1] + R[1][2] * vector2[2]
        nu_vec[2] = R[2][0] * vector2[0] + R[2][1] * vector2[1] + R[2][2] * vector2[2]

        node3 = node2 + nu_vec

    return node3

def data_splitby_xy(ld, datapoints, x0, x1, ne_parent, ne_current, point_limit):
    # Decides which side of a line a random point is on.
    # !Given a directed line from point p0(x0, y0) to p1(x1, y1), you can use the following condition to decide whether a point p2(x2, y2) is on the left of the line, on the right, or on the same line:
    # value = (x1 - x0)(y2 - y0) - (x2 - x0)(y1 - y0)
    # if value > 0, p2 is on the left side of the line.
    #
    npoints = 0
    dat1 = 0
    dat2 = 0
    ss = [True, True]
    nd1_1st = 0
    nd2_1st = 0
    nde_change1 = 0
    nde_change2 = 0
    for nd in range(0, len(datapoints)):
        nsp = ld[nd]

        if nsp == ne_parent:  # data point belongs to this element
            npoints = npoints + 1
            checkvalue = (x1[0] - x0[0]) * (datapoints[nd][1] - x0[1]) - (datapoints[nd][0] - x0[0]) * (x1[1] - x0[1])
            if checkvalue >= 0:
                if dat1 == 0:
                    nd1_1st = nd
                dat1 = dat1 + 1
                ld[nd] = ne_current + 1
                nde_change1 = ne_current + 1
            else:
                if dat2 == 0:
                    nd2_1st = nd
                dat2 = dat2 + 1
                ld[nd] = ne_current + 2
                nde_change2 = ne_current + 2
    if npoints < point_limit:
        ss[0] = False
        ss[1] = False
    else:
        ss[0] = True
        ss[1] = True
        if dat1 < point_limit:
            ss[0] = False
        if dat2 < point_limit:
            ss[0] = False

    return {'nde_change1': nde_change1, 'nde_change2': nde_change2, 'ss': ss}

def calc_branch_direction(vector):
    length = 0.0
    for i in range(0, len(vector)):
        length = length + vector[i] ** 2
    length = np.sqrt(length)

    branch_direction = vector / length

    return branch_direction

def dist_two_vectors(vector1, vector2):
    dist = np.sqrt((vector1[0] - vector2[0]) ** 2 + (vector1[1] - vector2[1]) ** 2 + (vector1[2] - vector2[2]) ** 2)

    return dist

def group_elem_parent_term(ne_parent, elem_downstream):
    parentlist = np.zeros(10)
    ne_old = np.zeros(10)
    ntemp_list = np.zeros(10)
    ne_temp = np.zeros(10)

    NT_BNS = 1
    ne_old[0] = ne_parent
    ne_count = 0
    ntemp_list[ne_count] = 0
    while NT_BNS != 0:
        num_nodes = NT_BNS
        NT_BNS = 0
        for m in range(1, num_nodes + 1):
            ne0 = int(ne_old[m])
            for n in range(0, int(elem_downstream[ne0][0])):
                NT_BNS = NT_BNS + 1
                ne_temp[NT_BNS] = elem_downstream[ne0][n + 1]
        for n in range(1, NT_BNS + 1):
            ne_old[n] = ne_temp[n]
            ne_count = ne_count + 1
            ntemp_list[ne_count] = ne_temp[n]
    ntemp_list[0] = ne_count
    num_in_list = 0
    for noelem in range(1, ne_count + 1):
        ne = int(ntemp_list[noelem])
        if elem_downstream[ne][0] == 0:
            num_in_list = num_in_list + 1
            parentlist[num_in_list - 1] = ne
    parentlist.resize(num_in_list)

    print('Grouped by parent,' + str(ne_parent) + ' No in parent list,' + str(num_in_list))

    return parentlist

def data_to_mesh(ld, datapoints, parentlist, node_loc, elems):
    # Assigns data(seed) points to the closest ending of branches in the current generation.
    for nd in range(0, len(datapoints)):
        if ld[nd] != 0:
            ne_min = 0
            min_dist = 1e10
            for noelem in range(0, len(parentlist)):
                ne = int(parentlist[noelem])
                np = int(elems[ne][2])
                dist = dist_two_vectors(node_loc[np][1:4], datapoints[nd])
                if dist < min_dist:
                    ne_min = ne
                    min_dist = dist
            ld[nd] = ne_min

    return ld

def umbilical_seed_geometry(volume, thickness, ellipticity, insertion_x, insertion_y, umb_artery_distance,
                            umb_artery_length, datapoints):
    # Creating a basis for a branching geometry which assumes a simple umbilical cord structure, with two arteries,

    # Calulate axis dimensions of ellipsoid with given volume, thickness and ellipticity
    radii = pg_utilities.calculate_ellipse_radii(volume, thickness, ellipticity)
    z_radius = radii['z_radius']
    x_radius = radii['x_radius']
    y_radius = radii['y_radius']
    # initialise node and element arrays
    node_loc = np.zeros((6, 4))
    elems = np.zeros((5, 3))
    elem_upstream = np.zeros((5, 3))
    elem_downstream = np.zeros((5, 3))

    # basic umbilical artery structure
    node_loc[0][0] = 0
    node_loc[0][1] = insertion_x
    node_loc[0][2] = insertion_y
    node_loc[0][3] = pg_utilities.z_from_xy(node_loc[0][1], node_loc[0][2], x_radius, y_radius,
                                            z_radius) + umb_artery_length + 3.0  # dummy branch 3mm long by default

    # node 2 is 3 mm up from node 1 in the z direction
    node_loc[1][0] = 1
    node_loc[1][1] = insertion_x
    node_loc[1][2] = insertion_y
    node_loc[1][3] = pg_utilities.z_from_xy(node_loc[0][1], node_loc[0][2], x_radius, y_radius,
                                            z_radius) + umb_artery_length

    # node 3 & 4 is the start of the 'umbilical artery'
    node_loc[2][0] = 2
    node_loc[2][1] = insertion_x
    node_loc[2][2] = insertion_y - umb_artery_distance / 2.0
    node_loc[2][3] = pg_utilities.z_from_xy(node_loc[0][1], node_loc[0][2], x_radius, y_radius,
                                            z_radius) + umb_artery_length
    node_loc[3][0] = 3
    node_loc[3][1] = insertion_x
    node_loc[3][2] = insertion_y + umb_artery_distance / 2.0
    node_loc[3][3] = pg_utilities.z_from_xy(node_loc[0][1], node_loc[0][2], x_radius, y_radius,
                                            z_radius) + umb_artery_length

    # node 5 and 6 'hit' the chorionic plate.
    node_loc[4][0] = 4
    node_loc[4][1] = insertion_x
    node_loc[4][2] = insertion_y - umb_artery_distance / 2.0
    node_loc[4][3] = pg_utilities.z_from_xy(node_loc[4][1], node_loc[4][2], x_radius, y_radius, z_radius)
    node_loc[5][0] = 5
    node_loc[5][1] = insertion_x
    node_loc[5][2] = insertion_y + umb_artery_distance / 2.0
    node_loc[5][3] = pg_utilities.z_from_xy(node_loc[5][1], node_loc[5][2], x_radius, y_radius, z_radius)
    # element locations
    elems[0, :] = [0, 0, 1]
    elem_upstream[0][0] = 0
    elem_downstream[0][0] = 2
    elem_downstream[0][1] = 1
    elem_downstream[0][2] = 2

    elems[1, :] = [1, 1, 2]
    elem_upstream[1][0] = 1
    elem_upstream[1][1] = 0
    elem_downstream[1][0] = 1
    elem_downstream[1][1] = 3

    elems[2, :] = [2, 1, 3]
    elem_upstream[2][0] = 1
    elem_upstream[2][1] = 0
    elem_downstream[2][0] = 1
    elem_downstream[2][1] = 4

    elems[3, :] = [3, 2, 4]
    elem_upstream[3][0] = 1
    elem_upstream[3][1] = 1
    elem_downstream[3][0] = 2
    elem_downstream[3][1] = 5
    elem_downstream[3][2] = 6

    elems[4, :] = [4, 3, 5]
    elem_upstream[4][0] = 1
    elem_upstream[4][1] = 2
    elem_downstream[4][0] = 2
    elem_downstream[4][1] = 7
    elem_downstream[4][2] = 8

    # split datapoints by x and y insertion points
    ld = np.zeros(len(datapoints))
    for nd in range(0, len(datapoints)):
        if (datapoints[nd][0] > insertion_x) and (datapoints[nd][1] > insertion_y):
            ld[nd] = 1
        elif (datapoints[nd][0] > insertion_x) and (datapoints[nd][1] < insertion_y):
            ld[nd] = 2
        elif (datapoints[nd][0] < insertion_x) and (datapoints[nd][1] < insertion_y):
            ld[nd] = 3
        else:
            ld[nd] = 4

    # Calculate centre of mass for each seedpoint set
    com1 = mesh_com(1, ld, datapoints)
    com2 = mesh_com(2, ld, datapoints)
    com3 = mesh_com(3, ld, datapoints)
    com4 = mesh_com(4, ld, datapoints)

    ##CREATE NEW NODES ON CHORION SURFACE HALF WAY TO GROUP COM

    node_loc = np.append(node_loc, np.zeros((4, 4)), axis=0)
    elems = np.append(elems, np.zeros((4, 3)), axis=0)
    elem_upstream = np.append(elem_upstream, np.zeros((4, 3)), axis=0)
    elem_downstream = np.append(elem_downstream, np.zeros((4, 3)), axis=0)
    node_loc[6][0] = 6
    node_loc[6][1:4] = com1 / 2.0
    node_loc[6][3] = pg_utilities.z_from_xy(node_loc[6][1], node_loc[6][2], x_radius, y_radius, z_radius)

    elems[7, :] = [7, 5, 6]
    elem_upstream[7][0] = 1
    elem_upstream[7][1] = 4
    elem_downstream[7][0] = 0

    node_loc[7][0] = 7
    node_loc[7][1:4] = com2 / 2.0
    node_loc[7][3] = pg_utilities.z_from_xy(node_loc[7][1], node_loc[7][2], x_radius, y_radius, z_radius)

    elems[5, :] = [5, 4, 7]
    elem_upstream[5][0] = 1
    elem_upstream[5][1] = 3
    elem_downstream[5][0] = 0

    node_loc[8][0] = 8
    node_loc[8][1:4] = com3 / 2.0
    node_loc[8][3] = pg_utilities.z_from_xy(node_loc[8][1], node_loc[8][2], x_radius, y_radius, z_radius)

    elems[6, :] = [6, 4, 8]
    elem_upstream[6][0] = 1
    elem_upstream[6][1] = 3
    elem_downstream[6][0] = 0

    node_loc[9][0] = 9
    node_loc[9][1:4] = com4 / 2.0
    node_loc[9][3] = pg_utilities.z_from_xy(node_loc[9][1], node_loc[9][2], x_radius, y_radius, z_radius)

    elems[8, :] = [8, 5, 9]
    elem_upstream[8][0] = 1
    elem_upstream[8][1] = 4
    elem_downstream[8][0] = 0

    return {'umb_nodes': node_loc, 'umb_elems': elems, 'elem_up': elem_upstream, 'elem_down': elem_downstream}

def mesh_com(ld_val, ld, datapoints):
    dat = 0

    com = np.zeros(3)
    for nd in range(0, len(datapoints)):
        nsp = ld[nd]
        if nsp == ld_val:
            dat = dat + 1
            for nj in range(0, 3):
                com[nj] = com[nj] + datapoints[nd][nj]
    if dat != 0:
        com = com / dat

    return com